一、Comparable与Comparator的相同点
Comparable和Comparator都是java的一个接口,多用于实现集合中元素的比较及排序。
当我们自定义一个类时,如果需要规定其中的排序规则时,我们就必须用到比较接口。例如:
public class Person{ private String name;//姓名 private int age;//年龄 private double height;//身高 }
我们定义了一个类,想规定其按照年龄进行比较,并且将Person类的对象存在List集合中,调用集合工具类中的 Collections.sort 排序方法,这时不能得到我们想要得到的结果。而我们 String 却不然,如果我们讲 String 存入到List集合中,它会按照一定的顺序进行排序,因为我们String类中实现了 Comparable 接口,并重写了接口中的 compareTo 方法,如下:
public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; }
所以我们需要给自己定义的类定义一个比较的规则,我们就需要实现一个比较接口。
二、Comparable 和 Comparator 的区别
Comparable
Comparable 定义在想要实现排序对象的类的内部,并且重写compareTo方法,例如:
public class Person implements Comparable<Person>{ private String name;//姓名 private int age;//年龄 private double height;//身高 /** * 方法的作用就是定义比较规则 * 返回值类型为int类型,取值范围分别为正数,负数,0 * 正数:大于 * 负数:小于 * 0:等于 * @param p * @return int */ @Override public int compareTo(Person p) { return this.age - p.age; } }
当一个类实现了Comparable接口并重写了CompareTo方法时,我们使用Collections.sort进行排序的话,会自动调用其自定义的比较规则进行比较排序,CompareTo方法的返回值为int类型,有三种情况,分别为:
1、自定义的比较规则中,比较着大于被比较者时,则返回正数;
2、自定义的比较规则中,比较着小于被比较者时,则返回负数;
3、自定义的比较规则中,比较着等于被比较者时,则返回0;
Comparator
Comparator 定义在想要实现排序对象的类的外部,并且重写compare方法。
当一个类未定义比较规则,并且我们想要对其进行排序时,会使用你匿名内部类的方式或者重新自定义一个类并实现Comparator接口的方式来达到这个目的,例如:
匿名内部类方式:
public class PersonTest { public static void main(String[] args) { Person p1 = new Person("张三", 18, 180); Person p2 = new Person("李四", 20, 165); Person p3 = new Person("王五", 15, 175); List<Person> list = new ArrayList(); list.add(p1); list.add(p2); list.add(p3); Collections.sort(list, new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getAge()-o2.getAge(); } }); System.out.println(list); } }
自定义类实现Comparator接口
public class PersonComparator implements Comparator<Person> { @Override public int compare(Person o1, Person o2) { return o1.getAge()-o2.getAge(); } } public class PersonTest { public static void main(String[] args) { Person p1 = new Person("张三", 18, 180); Person p2 = new Person("李四", 20, 165); Person p3 = new Person("王五", 15, 175); List<Person> list = new ArrayList(); list.add(p1); list.add(p2); list.add(p3); Collections.sort(list, new PersonComparator()); System.out.println(list); } }
其实,从原理上来讲它们没有什么太大的不同,都是实现了 Comparator 接口并重写了 Compare 方法,只是写法上有些区别。当然从复用性的角度来讲,还是自定义的复用性更高一些,这里还需要实际看需求决定。它的比较规则和上述的Comparable中的CompareTo方法一样, Compare 方法的返回值也为int类型,也有三种情况,分别为:
1、返回值类型为正数时,代表o1 > o2
2、返回值类型为负数时,代表o1 < o2
3、返回值类型为0时,代表o1 = o2
三、注意事项
无论是实现Comparable接口还是Comparator接口都需要指定泛型。
四、总结
实际上述两种方式各有利弊,实现Comparable使用比较简单,只要是实现了Comparable接口的类的对象,我们可以直接进行比较,但是在一些开发中我们开始未考虑到这里的情况下,想要改变就需要改变其源代码,不够方便;但是Comparator则不然,它可以在不修改源码的基础上,重新自定义一个比较器,这样降低了我们代码之间的耦合性,当我们之后想要改变一个比较算法时,也可以很方便的进行改变。我们只要重新定义一个比较规则即可。
五、课后作业
习题:
一个班内有5名学生,用java写一段代码,将学生们按照年龄从大到小排序,如果年龄一样则按身高排序(高到低),如果身高也一样,按体重排序(轻到重)。
答案:
Stu学生类
public class Stu implements Comparable<Stu>{ private Integer id; private String name; private Integer age; private Integer height;//165cm private Integer weight;//51kg public Stu() { } public Stu(Integer id, String name, Integer age, Integer height, Integer weight) { this.id = id; this.name = name; this.age = age; this.height = height; this.weight = weight; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Integer getHeight() { return height; } public void setHeight(Integer height) { this.height = height; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", height=" + height + ", weight=" + weight + '}'; } @Override public int compareTo(Stu o) { /* 1.按年龄从大到小排序 2.如果年龄一样则按照身高排序(高到低) 3.如果身高一样则按照体重排序(轻到重) */ if (age.compareTo(o.getAge())!=0) return o.getAge().compareTo(age); if (height.compareTo(o.getHeight())!=0) return o.getHeight().compareTo(height); return weight.compareTo(o.getWeight()); } }
StuTests学生测试类
public class StuTests { public static void main(String[] args) { List<Stu> list = new ArrayList<>(); Stu stu1 = new Stu(1002,"tom",21,170,55); Stu stu2 = new Stu(1001,"tony",21,170,56); Stu stu3 = new Stu(1005,"amy",20,180,51); Stu stu4 = new Stu(1004,"jack",23,184,59); Stu stu5 = new Stu(1003,"rose",23,150,66); list.add(stu1); list.add(stu2); list.add(stu3); list.add(stu4); list.add(stu5); list.forEach(stu -> System.out.println(stu)); /* Stu{id=1002, name='tom', age=21, height=170, weight=55} Stu{id=1001, name='tony', age=21, height=170, weight=56} Stu{id=1005, name='amy', age=20, height=180, weight=51} Stu{id=1004, name='jack', age=23, height=184, weight=59} Stu{id=1003, name='rose', age=23, height=150, weight=66} */ } }标签:Comparable,Comparator,区别,age,list,Stu,height,Person,public From: https://www.cnblogs.com/fulaien/p/17201312.html