Java 中 Comparable 和 Comparator 比较

目录:

  1. Comparable
  2. Comparator
  3. Comparable 和 Comparator比较
  4. 第二个例子 之 Comparator
  5. 第二个例子 之 Comparable

Comparable 

Comparable 简介

Comparable 是排序接口。

若一个类实现了Comparable接口,就意味着“该类支持排序”。  即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。

此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。

Comparable 定义

Comparable 接口仅仅只包括一个函数,它的定义如下:

package java.lang;
import java.util.*;

public interface Comparable<T> {
    public int compareTo(T o);
}

说明:

假设我们通过 x.compareTo(y) 来“比较x和y的大小”。若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。

Comparator

Comparator 简介

Comparator 是比较器接口。

我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。

也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。

Comparator 定义

Comparator 接口仅仅只包括两个个函数,它的定义如下:

package java.util;

public interface Comparator<T> {

    int compare(T o1, T o2);

    boolean equals(Object obj);
}

说明:
(01) 若一个类要实现Comparator接口:它一定要实现compareTo(T o1, T o2) 函数,但可以不实现  equals(Object obj) 函数。

为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。

(02) int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意着“o1  等于o2”;返回“正数”,意味着“o1大于o2”。

Comparator 和 Comparable 比较

Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。
而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。

我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

我们通过一个测试程序来对这两个接口进行说明。代码如下:

Person

/**
 * @desc Person类。
 *       Person实现了Comparable接口,这意味着Person本身支持排序
 */
public class Person implements Comparable<Person>{
    int age;
    String name;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    /**
     * 重写toString方法
     */
    public String toString() {
        return name + " - " +age;
    }

    /**
     * 重写equals方法
     * 比较两个Person是否相等:若它们的name和age都相等,则认为它们相等
     */
    boolean equals(Person person) {
        if (this.age == person.age && this.name == person.name)
            return true;
        return false;
    }

    /**
     * @desc 实现 “Comparable<String>” 的接口,即重写compareTo<T t>函数。
     *  这里是通过“person的名字”进行比较的
     */
    @Override
    public int compareTo(Person person) {
        return name.compareTo(person.name);
        //return this.name - person.name;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

AscAgeComparator比较器

import java.util.Comparator;

/**
 * @desc AscAgeComparator比较器
 *       它是“Person的age的升序比较器”
 */
public  class AscAgeComparator implements Comparator<Person> {

    @Override
    public int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }
}

DescAgeComparator比较器

import java.util.Comparator;

/**
 * @desc DescAgeComparator比较器
 *       它是“Person的age的升序比较器”
 */
public  class DescAgeComparator implements Comparator<Person> {

    @Override
    public int compare(Person p1, Person p2) {
        return p2.getAge() - p1.getAge();
    }
}

Test类

import java.util.*;
/**
 * @desc "Comparator"和“Comparable”的比较程序。
 *   (01) "Comparable"
 *   它是一个排序接口,只包含一个函数compareTo()。
 *   一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort() 或 Collections.sort()进行排序。
 *   (02) "Comparator"
 *   它是一个比较器接口,包括两个函数:compare() 和 equals()。
 *   一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。
 *
 *   综上所述:Comparable是内部比较器,而Comparator是外部比较器。
 *   一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。
 */
public class Test{

    public static void main(String[] args) {
        // 新建ArrayList(动态数组)
        ArrayList<Person> list = new ArrayList<Person>();
        // 添加对象到ArrayList中
        list.add(new Person("ccc", 20));
        list.add(new Person("AAA", 30));
        list.add(new Person("bbb", 10));
        list.add(new Person("ddd", 40));

        // 打印list的原始序列
        System.out.printf("Original  sort, list:%s\n", list);

        // 对list进行排序
        // 这里会根据“Person实现的Comparable<String>接口”进行排序,即会根据“name”进行排序
        Collections.sort(list);
        System.out.printf("Name      sort, list:%s\n", list);

        // 通过“比较器(AscAgeComparator)”,对list进行排序
        // AscAgeComparator的排序方式是:根据“age”的升序排序
        Collections.sort(list, new AscAgeComparator());
        System.out.printf("Asc(age)  sort, list:%s\n", list);

        // 通过“比较器(DescAgeComparator)”,对list进行排序
        // DescAgeComparator的排序方式是:根据“age”的降序排序
        Collections.sort(list, new DescAgeComparator());
        System.out.printf("Desc(age) sort, list:%s\n", list);

        // 判断两个person是否相等
        testEquals();
    }

    /**
     * @desc 测试两个Person比较是否相等。
     *   由于Person实现了equals()函数:若两person的age、name都相等,则认为这两个person相等。
     *   所以,这里的p1和p2相等。
     *
     *   TODO:若去掉Person中的equals()函数,则p1不等于p2
     */
    private static void testEquals() {
        Person p1 = new Person("eee", 100);
        Person p2 = new Person("eee", 100);
        if (p1.equals(p2)) {
            System.out.printf("%s EQUAL %s\n", p1, p2);
        } else {
            System.out.printf("%s NOT EQUAL %s\n", p1, p2);
        }
    }
}

答案:

Original  sort, list:[ccc - 20, AAA - 30, bbb - 10, ddd - 40]
Name      sort, list:[AAA - 30, bbb - 10, ccc - 20, ddd - 40]
Asc(age)  sort, list:[bbb - 10, ccc - 20, AAA - 30, ddd - 40]
Desc(age) sort, list:[ddd - 40, AAA - 30, ccc - 20, bbb - 10]
eee - 100 EQUAL eee - 100

第二个例子 之 Comparator

Student类

public class Student {
    private int studentId;
    private String studentName;
    private int age;
    public Student(int studentId , String studentName, int age){
        this.studentId=studentId;
        this.studentName=studentName;
        this.age=age;
    }
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getStudentName() {
        return studentName;
    }
    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

}

Test类

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Comparator<Student> comparator = new Comparator<Student>() {
            public int compare(Student s1, Student s2) {
                // 先排年龄
                if (s1.getAge() != s2.getAge()) {
                    return s1.getAge() - s2.getAge();
                } else if (!s1.getStudentName().equals(s2.getStudentName())) {
                    // 年龄相同则按姓名排序
                    return s1.getStudentName().compareTo(s2.getStudentName());
                } else {
                    // 姓名也相同则按学号排序
                    return s1.getStudentId() - s2.getStudentId();
                }
            }
        };
         Student stu1 = new Student (1,"zhangsan",28);
         Student stu2 = new Student (2,"zhagnsan",19);
         Student stu3 = new Student (3,"wangwu",19);
         Student stu4 = new Student (4,"wangwu",19);
         Student stu5 = new Student (5,"zhaoliu",18);

          ArrayList<Student> list = new ArrayList<Student>();
          list.add(stu1);
          list.add(stu2);
          list.add(stu3);
          list.add(stu4);
          list.add(stu5);
          //这里就会自动根据规则进行排序
          Collections.sort(list,comparator);
          for(int i=0;i<list.size();i++){
              Student stu=list.get(i);
              System.out.println("年龄:"+stu.getAge()+"   姓名:"+stu.getStudentName()+"   学号:"+stu.getStudentId());
          }

    }

}

第二个例子 之 Comparable

Student2类

public class Student2 implements Comparable<Student2>{  //必须实现CompareTo()

    private int studentId;
    private String studentName;
    private int age;
    public Student2(int studentId , String studentName, int age){
        this.studentId=studentId;
        this.studentName=studentName;
        this.age=age;
    }
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getStudentName() {
        return studentName;
    }
    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int compareTo(Student2 o) {
        if(age!=o.getAge()){
            return age-o.getAge();
        }else if(!studentName.equals(o.getStudentName())){
            return studentName.compareTo(o.getStudentName());
        }else {
            return studentId-o.getStudentId();
        }
    }
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof Student2){
            Student2 stu=(Student2)obj;
            if((age==stu.getAge())&&(studentName.equals(stu.getStudentName()))&&(studentId==stu.getStudentId())){
                return true;
            }else
                return true;
        }else{
            return false;
        }
    }  

}

Test2类

public class test2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Student2 stu1 = new Student2 (1,"zhangsan",28);
        Student2 stu2 = new Student2 (2,"zhagnsan",19);
        Student2 stu3 = new Student2 (3,"wangwu",19);
        Student2 stu4 = new Student2 (4,"wangwu",19);
        Student2 stu5 = new Student2 (5,"zhaoliu",18);

          ArrayList<Student2> list = new ArrayList<Student2>();
          list.add(stu1);
          list.add(stu2);
          list.add(stu3);
          list.add(stu4);
          list.add(stu5);
          //这里就会自动根据规则进行排序
          Collections.sort(list);
          for(int i=0;i<list.size();i++){
              Student2 stu=list.get(i);
              System.out.println("年龄:"+stu.getAge()+"   姓名:"+stu.getStudentName()+"   学号:"+stu.getStudentId());
          }

    }
}

第二个例子 之 Comparator   第二个例子 之 Comparable 的答案都为:

年龄:18   姓名:zhaoliu   学号:5
年龄:19   姓名:wangwu   学号:3
年龄:19   姓名:wangwu   学号:4
年龄:19   姓名:zhagnsan   学号:2
年龄:28   姓名:zhangsan   学号:1

文章出自:http://www.cnblogs.com/skywang12345/p/3324788.html

http://www.cnblogs.com/fthjane/p/4797159.html

Java 中 Comparable 和 Comparator 比较的更多相关文章

  1. Java中Comparable和Comparator接口区别分析

    Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...

  2. Java 中 Comparable 和 Comparator 比较(转)

    转自http://www.cnblogs.com/skywang12345/p/3324788.html 本文,先介绍Comparable 和Comparator两个接口,以及它们的差异:接着,通过示 ...

  3. Java中Comparable与Comparator的区别

    相同 Comparable和Comparator都是用来实现对象的比较.排序 要想对象比较.排序,都需要实现Comparable或Comparator接口 Comparable和Comparator都 ...

  4. Java中Comparable和Comparator区别小结

    一.Comparable简介 Comparable是排序接口.若一个类实现了Comparable接口,就意味着该类支持排序.实现了Comparable接口的类的对象的列表或数组可以通过Collecti ...

  5. Java中Comparable和Comparator你知多少?

    前言: 我喜欢这种遨游在Java的世界里,精心研究学习新鲜事物的感觉,即便再小再细再微不足道的东西,也让我乐此不疲,同时我也更愿意将我所会的东西分享出来供大家学习以及方便自己日后回顾.好了,闲话不多说 ...

  6. java中Comparable和Comparator两种比较器的区别

    Comparable和Comparator接口都是为了对类进行比较,众所周知,诸如Integer,double等基本数据类型,java可以对他们进行比较,而对于类的比较,需要人工定义比较用到的字段比较 ...

  7. 【转载】Java中Comparable和Comparator比较

    [本文转自]http://www.cnblogs.com/skywang12345/p/3324788.html Comparable 简介 Comparable 是排序接口. 若一个类实现了Comp ...

  8. 你能说说Java中Comparable和Comparator的区别吗

    之前面试中被问到这个问题,当时不屑(会)回答,下来特意查了查,整理如下. Java 中为我们提供了两种比较机制:Comparable 和 Comparator,二者都是用来实现对象的比较.排序. 下面 ...

  9. 夯实Java基础(十五)——Java中Comparable和Comparator

    1.前言 对于Java中的对象,我们只能使用基本运算符==.!=来判断一下地址是否相等,不能使用>.<来比较大小.但是在实际的开发中,我们需要对对象进行排序,也就是比较大小,那么应该如何实 ...

随机推荐

  1. Metasploitable 2系列教程:信息收集

    Metasploitable 2 系统是一个基于ubuntu 的系统.其设计的最初目的为安全工具测试和常见漏洞攻击演示.而在这篇关于 Metasploit 的教程中,我们将列举有关 Metasploi ...

  2. Nginx下配置SSL安全协议

    生成证书: # cd /usr/local/nginx/conf # openssl genrsa -des3 -out server.key 1024 # openssl req -new -key ...

  3. [Android Tips] 16. Update Android SDK from command-line

    $ cd $ANROID_HOME $ tools/android update sdk -u -s 参数 -s --no-https : Uses HTTP instead of HTTPS (th ...

  4. sharding-jdbc-how2work 当当的sharding-jdbc剖析(查询)

    1. 以JDBC作为出发点 1.1 重新实现了JDBC的几个接口 实现javax.sql.DataSource接口  ShardingDataSource实现java.sql.Connection接口 ...

  5. Objective-C Block

    OC中block的语法实在是太别扭了,不知道是不是我太孤陋寡闻了...在此记录一下,以供日后查找使用. 引用:http://goshdarnblocksyntax.com As a local var ...

  6. URL中文乱码处理总结(转)

    转自:http://www.cnblogs.com/xirongliu/archive/2012/09/06/2674196.html 问题:传递中文参数的时候,接收页面出现乱码问题?当跨域操作,两套 ...

  7. C语言回顾-函数和位运算

    1.函数的概述 功能独立的代码块 C语言由若干函数组成 1)从定义分,库函数和用户定义函数两种 2)从返回值分,有返回值函数和无返回值函数 3)从参数分,无参函数和有参函数 2.形参和实参 1)形参定 ...

  8. 提高Oracle的WHERE语句性能一些原则

    索引是表的一个概念部分 , 用来提高检索数据的效率, ORACLE 使用了一个复杂的自平衡 B-tree 结构 . 通常 , 通过索引查询数据比全表扫描要快 . 当 ORACLE 找出执行查询和 Up ...

  9. [转]MySQL5.6新特性之Multi-Range Read

    这几天看到mrr的东西,刚好看到以前我们组的一个小伙的博客,我看挺全的,就转过来了,原博客地址请戳 一 介绍    MySQL 5.6版本提供了很多性能优化的特性,其中之一就是 Multi-Range ...

  10. wex5 教程 之 图文讲解 bind-css和bind-sytle的异同

    wex5作为网页开发利器,在前台UI数据交互设计中大量使用了绑定技术,即官方视频教学中也提到了KO,实质是数据绑定与追踪.在前台组件的属性中,为我们提供了两个重要的样式绑定属性,bind-css和bi ...