爱程序网

Java 中 Comparable 和 Comparator 比较

来源: 阅读:

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
View Code

 

 

第二个例子 之 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
View Code

 

 

 

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

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

关于爱程序网 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助