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 接口仅仅只包括一个函数,它的定义如下:

  1. package java.lang;
  2. import java.util.*;
  3.  
  4. public interface Comparable<T> {
  5. public int compareTo(T o);
  6. }

说明:

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

Comparator

Comparator 简介

Comparator 是比较器接口。

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

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

Comparator 定义

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

  1. package java.util;
  2.  
  3. public interface Comparator<T> {
  4.  
  5. int compare(T o1, T o2);
  6.  
  7. boolean equals(Object obj);
  8. }

说明:
(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

  1. /**
  2. * @desc Person类。
  3. * Person实现了Comparable接口,这意味着Person本身支持排序
  4. */
  5. public class Person implements Comparable<Person>{
  6. int age;
  7. String name;
  8.  
  9. public Person(String name, int age) {
  10. this.name = name;
  11. this.age = age;
  12. }
  13. /**
  14. * 重写toString方法
  15. */
  16. public String toString() {
  17. return name + " - " +age;
  18. }
  19.  
  20. /**
  21. * 重写equals方法
  22. * 比较两个Person是否相等:若它们的name和age都相等,则认为它们相等
  23. */
  24. boolean equals(Person person) {
  25. if (this.age == person.age && this.name == person.name)
  26. return true;
  27. return false;
  28. }
  29.  
  30. /**
  31. * @desc 实现 “Comparable<String>” 的接口,即重写compareTo<T t>函数。
  32. * 这里是通过“person的名字”进行比较的
  33. */
  34. @Override
  35. public int compareTo(Person person) {
  36. return name.compareTo(person.name);
  37. //return this.name - person.name;
  38. }
  39.  
  40. public String getName() {
  41. return name;
  42. }
  43.  
  44. public int getAge() {
  45. return age;
  46. }
  47. }

AscAgeComparator比较器

  1. import java.util.Comparator;
  2.  
  3. /**
  4. * @desc AscAgeComparator比较器
  5. * 它是“Person的age的升序比较器”
  6. */
  7. public class AscAgeComparator implements Comparator<Person> {
  8.  
  9. @Override
  10. public int compare(Person p1, Person p2) {
  11. return p1.getAge() - p2.getAge();
  12. }
  13. }

DescAgeComparator比较器

  1. import java.util.Comparator;
  2.  
  3. /**
  4. * @desc DescAgeComparator比较器
  5. * 它是“Person的age的升序比较器”
  6. */
  7. public class DescAgeComparator implements Comparator<Person> {
  8.  
  9. @Override
  10. public int compare(Person p1, Person p2) {
  11. return p2.getAge() - p1.getAge();
  12. }
  13. }

Test类

  1. import java.util.*;
  2. /**
  3. * @desc "Comparator"和“Comparable”的比较程序。
  4. * (01) "Comparable"
  5. * 它是一个排序接口,只包含一个函数compareTo()。
  6. * 一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort() 或 Collections.sort()进行排序。
  7. * (02) "Comparator"
  8. * 它是一个比较器接口,包括两个函数:compare() 和 equals()。
  9. * 一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。
  10. *
  11. * 综上所述:Comparable是内部比较器,而Comparator是外部比较器。
  12. * 一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。
  13. */
  14. public class Test{
  15.  
  16. public static void main(String[] args) {
  17. // 新建ArrayList(动态数组)
  18. ArrayList<Person> list = new ArrayList<Person>();
  19. // 添加对象到ArrayList中
  20. list.add(new Person("ccc", 20));
  21. list.add(new Person("AAA", 30));
  22. list.add(new Person("bbb", 10));
  23. list.add(new Person("ddd", 40));
  24.  
  25. // 打印list的原始序列
  26. System.out.printf("Original sort, list:%s\n", list);
  27.  
  28. // 对list进行排序
  29. // 这里会根据“Person实现的Comparable<String>接口”进行排序,即会根据“name”进行排序
  30. Collections.sort(list);
  31. System.out.printf("Name sort, list:%s\n", list);
  32.  
  33. // 通过“比较器(AscAgeComparator)”,对list进行排序
  34. // AscAgeComparator的排序方式是:根据“age”的升序排序
  35. Collections.sort(list, new AscAgeComparator());
  36. System.out.printf("Asc(age) sort, list:%s\n", list);
  37.  
  38. // 通过“比较器(DescAgeComparator)”,对list进行排序
  39. // DescAgeComparator的排序方式是:根据“age”的降序排序
  40. Collections.sort(list, new DescAgeComparator());
  41. System.out.printf("Desc(age) sort, list:%s\n", list);
  42.  
  43. // 判断两个person是否相等
  44. testEquals();
  45. }
  46.  
  47. /**
  48. * @desc 测试两个Person比较是否相等。
  49. * 由于Person实现了equals()函数:若两person的age、name都相等,则认为这两个person相等。
  50. * 所以,这里的p1和p2相等。
  51. *
  52. * TODO:若去掉Person中的equals()函数,则p1不等于p2
  53. */
  54. private static void testEquals() {
  55. Person p1 = new Person("eee", 100);
  56. Person p2 = new Person("eee", 100);
  57. if (p1.equals(p2)) {
  58. System.out.printf("%s EQUAL %s\n", p1, p2);
  59. } else {
  60. System.out.printf("%s NOT EQUAL %s\n", p1, p2);
  61. }
  62. }
  63. }

答案:

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

第二个例子 之 Comparator

Student类

  1. public class Student {
  2. private int studentId;
  3. private String studentName;
  4. private int age;
  5. public Student(int studentId , String studentName, int age){
  6. this.studentId=studentId;
  7. this.studentName=studentName;
  8. this.age=age;
  9. }
  10. public int getStudentId() {
  11. return studentId;
  12. }
  13. public void setStudentId(int studentId) {
  14. this.studentId = studentId;
  15. }
  16. public String getStudentName() {
  17. return studentName;
  18. }
  19. public void setStudentName(String studentName) {
  20. this.studentName = studentName;
  21. }
  22. public int getAge() {
  23. return age;
  24. }
  25. public void setAge(int age) {
  26. this.age = age;
  27. }
  28.  
  29. }

Test类

  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.Comparator;
  4.  
  5. public class test {
  6.  
  7. /**
  8. * @param args
  9. */
  10. public static void main(String[] args) {
  11. Comparator<Student> comparator = new Comparator<Student>() {
  12. public int compare(Student s1, Student s2) {
  13. // 先排年龄
  14. if (s1.getAge() != s2.getAge()) {
  15. return s1.getAge() - s2.getAge();
  16. } else if (!s1.getStudentName().equals(s2.getStudentName())) {
  17. // 年龄相同则按姓名排序
  18. return s1.getStudentName().compareTo(s2.getStudentName());
  19. } else {
  20. // 姓名也相同则按学号排序
  21. return s1.getStudentId() - s2.getStudentId();
  22. }
  23. }
  24. };
  25. Student stu1 = new Student (1,"zhangsan",28);
  26. Student stu2 = new Student (2,"zhagnsan",19);
  27. Student stu3 = new Student (3,"wangwu",19);
  28. Student stu4 = new Student (4,"wangwu",19);
  29. Student stu5 = new Student (5,"zhaoliu",18);
  30.  
  31. ArrayList<Student> list = new ArrayList<Student>();
  32. list.add(stu1);
  33. list.add(stu2);
  34. list.add(stu3);
  35. list.add(stu4);
  36. list.add(stu5);
  37. //这里就会自动根据规则进行排序
  38. Collections.sort(list,comparator);
  39. for(int i=0;i<list.size();i++){
  40. Student stu=list.get(i);
  41. System.out.println("年龄:"+stu.getAge()+" 姓名:"+stu.getStudentName()+" 学号:"+stu.getStudentId());
  42. }
  43.  
  44. }
  45.  
  46. }

第二个例子 之 Comparable

Student2类

  1. public class Student2 implements Comparable<Student2>{ //必须实现CompareTo()
  2.  
  3. private int studentId;
  4. private String studentName;
  5. private int age;
  6. public Student2(int studentId , String studentName, int age){
  7. this.studentId=studentId;
  8. this.studentName=studentName;
  9. this.age=age;
  10. }
  11. public int getStudentId() {
  12. return studentId;
  13. }
  14. public void setStudentId(int studentId) {
  15. this.studentId = studentId;
  16. }
  17. public String getStudentName() {
  18. return studentName;
  19. }
  20. public void setStudentName(String studentName) {
  21. this.studentName = studentName;
  22. }
  23. public int getAge() {
  24. return age;
  25. }
  26. public void setAge(int age) {
  27. this.age = age;
  28. }
  29. public int compareTo(Student2 o) {
  30. if(age!=o.getAge()){
  31. return age-o.getAge();
  32. }else if(!studentName.equals(o.getStudentName())){
  33. return studentName.compareTo(o.getStudentName());
  34. }else {
  35. return studentId-o.getStudentId();
  36. }
  37. }
  38. @Override
  39. public boolean equals(Object obj) {
  40. if(obj instanceof Student2){
  41. Student2 stu=(Student2)obj;
  42. if((age==stu.getAge())&&(studentName.equals(stu.getStudentName()))&&(studentId==stu.getStudentId())){
  43. return true;
  44. }else
  45. return true;
  46. }else{
  47. return false;
  48. }
  49. }
  50.  
  51. }

Test2类

  1. public class test2 {
  2.  
  3. /**
  4. * @param args
  5. */
  6. public static void main(String[] args) {
  7. Student2 stu1 = new Student2 (1,"zhangsan",28);
  8. Student2 stu2 = new Student2 (2,"zhagnsan",19);
  9. Student2 stu3 = new Student2 (3,"wangwu",19);
  10. Student2 stu4 = new Student2 (4,"wangwu",19);
  11. Student2 stu5 = new Student2 (5,"zhaoliu",18);
  12.  
  13. ArrayList<Student2> list = new ArrayList<Student2>();
  14. list.add(stu1);
  15. list.add(stu2);
  16. list.add(stu3);
  17. list.add(stu4);
  18. list.add(stu5);
  19. //这里就会自动根据规则进行排序
  20. Collections.sort(list);
  21. for(int i=0;i<list.size();i++){
  22. Student2 stu=list.get(i);
  23. System.out.println("年龄:"+stu.getAge()+" 姓名:"+stu.getStudentName()+" 学号:"+stu.getStudentId());
  24. }
  25.  
  26. }
  27. }

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

  1. 年龄:18 姓名:zhaoliu 学号:5
  2. 年龄:19 姓名:wangwu 学号:3
  3. 年龄:19 姓名:wangwu 学号:4
  4. 年龄:19 姓名:zhagnsan 学号:2
  5. 年龄: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. php发送post请求到nodejs服务器

    curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data ); 改为 curl_setopt ( $ch, CURLOPT_POSTFIELDS, http_build ...

  2. Sublime Text3 常用快捷键

    1. 更改变量名的几种方法 a.选中变量,ctrl+d 一个个选择 b.选中变量,alt+F3   2.查找打开过的文件:Ctrl+P,然后输入最近的文件名就可以即时预览到文件内容. 3.ctrl+r ...

  3. linux下python安装到指定目录

    由于使用公司服务器时没有root权限,只能把python安装到个人文件夹下,使用源码包方式安装,这里记录一下. 1.python下载 cd到目录/users/w,在此目录下安装python.通过wge ...

  4. oracle: tochar(sysdate,'D')函数

    学习oracle时碰到tochar(sysdate,'D')函数,但是发现并不是星期几,如今天是20150317,周二,但是得到的值为3 开始以为是系统日期什么的原因,试了试 select to_ch ...

  5. thinkphp的钩子的两种配置和两种调用方法

    thinkphp的钩子行为类是一个比较难以理解的问题,网上有很多写thinkphp钩子类的文章,我也是根据网上的文章来设置thinkphp的钩子行为的,但根据这些网上的文章,我在设置的过程中,尝试了十 ...

  6. js实现发送短信验证码后的倒计时功能(无视页面刷新)

    [1].[代码] 这是页面上的发送验证码按钮 跳至 [1] [2] [3]<input id="second" type="button" value=& ...

  7. 4.用PHP打印出前一天的时间格式是2006-5-10 22:21:21

    echo date('Y-m-d H:i:s', strtotime('-1 days'));

  8. Android——初探Dagger2依赖注入

    1,在做项目时,经常需要在一个对象里去创建另一个对象的示例,这种行为是产生耦合的常见形式,对于一个大型项目来说,过多的相互依赖会导致代码难以维护,很容易就会碰到修改一个小需求需要大面积的修改各种代码, ...

  9. String.format中大括号的加入方法

    因为相对于string Builder  自己更喜欢 string.format 的形式拼接字符串。 今天在写代码的时候怎么都报错,弄的我很奇怪 最后发现问题出在字符串中出现大括号“{”的问题,我想这 ...

  10. 12. 星际争霸之php设计模式--模板模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...