比较器comparable和comparator的区别

比较器comparable和comparator的区别

Java提供了一个集合工具类,里面有排序方法,Collections使用它提供的方法来完成排序
注意:Collection不是Collections,Collections是在Collection上进行操作的集合的一个工具类,就如Arrays是数组的工具类

public class ComparableTest {
    public static void main(String[] args) {
        String names[] = { "Jack", "Adam", "Bob" };
        List<String> list = Arrays.asList(names);
        System.out.println(list);
        //排序的方式String已经替我们完成了
        //String会调用compareTo()方法实现排序的功能
        Collections.sort(list);
        System.out.println(list);
    }
}

String类实现Comparable接口,当调用sort规则时,String会调用compareTo方法实现排序功能

public class StudentComparable {
    public static void main(String[] args) {
        Student stu[] = {
                new Student("005", "Jackson", 3, 3, "football"),
                new Student("001", "Jerry", 1, 3, "football"),
                new Student("002", "Adam", 5, 2, "Tennis")
        };
        //错误原因:1Student没有实现Comparable接口
        //       2 没有指定排序规则(id、name、hobby)
        List<Student> list = Arrays.asList(stu);
        //如何比较排序?  Collections.sort方法进行排序,它会回调 容器中Student对象的 compareTo方法
        Collections.sort(list);
        for(Student student : list){
            System.out.println(student);
        }
    }

}
public class Student implements Comparable<Student>{

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getGrade() {
        return grade;
    }

    public void setGrade(int grade) {
        this.grade = grade;
    }

    public int getClassNo() {
        return classNo;
    }

    public void setClassNo(int classNo) {
        this.classNo = classNo;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", grade=" + grade + ", classNo=" + classNo + ", hobby=" + hobby
                + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + classNo;
        result = prime * result + grade;
        result = prime * result + ((hobby == null) ? 0 : hobby.hashCode());
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (classNo != other.classNo)
            return false;
        if (grade != other.grade)
            return false;
        if (hobby == null) {
            if (other.hobby != null)
                return false;
        } else if (!hobby.equals(other.hobby))
            return false;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    public Student(String id,String name,int grade,int classNo,String hobby) {
        this.id =id;
        this.name = name;
        this.grade = grade;
        this.classNo = classNo;
        this.hobby = hobby;
    }

    private String id;

    private String name;

    private int grade;

    private int classNo;

    private String hobby;

    /**
     * Comparable 的compareTo方法为我们提供了比较的功能,
     * 如何比较
     * 怎么做需要在Student类中实现
     * 我的规则:按照学生的ID进行排序
     */
    @Override
    public int compareTo(Student o) {
        //两个对象需要做比较  
        //this的id 如果大于 o 的id  返回的是正数
        //this的id 如果等于 o 的id  返回的是0
        //this的id 如果小于 o 的id  返回的是负数
//      int result = -(this.getId().compareTo(o.getId()));
//      return result;

//      if(this.getId().compareTo(o.getId()) >0){
//          return 1;
//      }else if(this.getId().compareTo(o.getId())<0){
//          return -1;
//      }
//      return 0;
       //按照年级进行排序
        if(this.getGrade() > o.getGrade()){
            return 1;
        }else if(this.getGrade() < o.getGrade()){
            return -1;
        }
        return 0;
    }
    //制定一个策略:输入1  id   输入2   name   输入3   爱好排序
}

如果只比较一次 ,可以使用匿名内部类节约资源

public class CheLueCompator {
    public static void main(String[] args) {
        Student stu[] = {
                new Student("005", "Jackson", 3, 6, "football"),
                new Student("001", "Zero", 1, 3, "basketball"),
                new Student("002", "Adam", 5, 2, "tennis")
        };
        List<Student> list = Arrays.asList(stu);

        sortList(list);
    }

    public static void sortList(List<Student> list) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入排序编号 1按照学生名称  2按照爱好  3按照班级编号");
        int num = input.nextInt();
        switch (num) {
        case 1:
            //两个参数 1需要排序的列表 2排序的策略   (按照名称排序)
            //匿名内部类:接口回调(由谁回调谁?)sort方法回调匿名内部类
            //好莱坞原则:sort理解为好莱坞 ,匿名内部类理解为演员
            //你不要找我,如果有需要我来找你,前提(匿名内部类需要向好莱坞进行注册)
            //如何注册(匿名内部类作为参数传入sort方法),sort方法需要的时候会回调匿名内部类的方法
            Collections.sort(list, new Comparator<Student>() {
                @Override
                public int compare(Student o1, Student o2) {
                    //调用String的compareTo()方法 
                    return o1.getName().compareTo(o2.getName());
                }
            });
            break;
        case 2:
            Collections.sort(list,new StuHobbyCompator());
             break;
        case 3:
            Collections.sort(list,new StuClassNoCompator());
            break;
        default:
            System.out.println("Error");
            break;
        }
        input.close();
        iteratorStu(list);
    }

    public static void iteratorStu(List<Student> list) {
        for(Student student : list){
            System.out.println(student);
        }
    }

}

Comparable和Comparator的区别

1、Comparable:在java.lang包,通常由实体类(Student)来实现,用来定义默认的排序规则
StudentComparable.java回调容器中Student对象的 compareTo方法
Comparator:在java.util包,排序的工具类,是一种策略,通常一个实体类(Student)有一种默认的排序法,还有多种排序策略
Comparable 定义在 Person类的内部:

public class Persion implements Comparable {..比较Person的大小..},
因为已经实现了比较器,那么我们的Person现在是一个可以比较大小的对象了,它的比较功能和String完全一样

2、Comparator
Comparator 是定义在Person的外部的, 此时我们的Person类的结构不需要有任何变化,如

public class Person{ String name; int age },

然后我们另外定义一个比较器:

public PersonComparator implements Comparator() {..比较Person的大小..},
用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
在PersonComparator里面实现了怎么比较两个Person的大小. 所以,用这种方法,当我们要对一个 personList进行排序的时候, 我们除了了要传递personList过去, 还需要把PersonComparator传递过去,因为怎么比较Person的大小是在PersonComparator里面实现的, 如:

Collections.sort( personList , new PersonComparator() ).
一个是自已完成比较,一个是外部程序实现比较的差别而已。
3、Comparator 和 Comparable 的实例
实现Comparable接口要覆盖compareTo方法, 在compareTo方法里面实现比较

public class Person implements Comparable {
     String name;
     int age
     public int compareTo(Person another) {
          int i = 0;
          i = name.compareTo(another.name); // 使用字符串的比较
          if(i == 0) { // 如果名字一样,比较年龄, 返回比较年龄结果
               return age - another.age;
          } else {
               return i; // 名字不一样, 返回比较名字的结果.
          }
     }
}

这时我们可以直接用 Collections.sort( personList ) 对其排序了.

实现Comparator需要覆盖 compare 方法:

public class Person{
     String name;
     int age
}
class PersonComparator implements Comparator { 
     public int compare(Person one, Person another) {
          int i = 0;
          i = one.name.compareTo(another.name); // 使用字符串的比较,即调用String的比较丰富
          if(i == 0) { // 如果名字一样,比较年龄,返回比较年龄结果
               return one.age - another.age;
          } else {
               return i; // 名字不一样, 返回比较名字的结果.
          }
     }
}
   Collections.sort( personList , new PersonComparator()) 可以对其排序

4、总结
两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码, 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值