Comparable接口和Comparator接口的使用和区别

川长思鸟来 2023-07-12 14:29 187阅读 0赞

Comparable

Comparable接口在JDK8中的源码:

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

用法:

  1. public class User implements Comparable<User>{
  2. private Integer id;
  3. private Integer age;
  4. public User() {
  5. }
  6. public User(Integer id, Integer age) {
  7. this.id = id;
  8. this.age = age;
  9. }
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setId(Integer id) {
  14. this.id = id;
  15. }
  16. public Integer getAge() {
  17. return age;
  18. }
  19. public void setAge(Integer age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "User{" +
  25. "id=" + id +
  26. ", age=" + age +
  27. '}';
  28. }
  29. public int compareTo(User o) {
  30. if(this.age > o.getAge()) {
  31. return 1;
  32. }else if(this.age < o.getAge()) {
  33. return -1;
  34. }else{
  35. return 0;
  36. }
  37. }
  38. }
  39. public class Test {
  40. public static void main(String[] args) {
  41. User user1 = new User(1, 14);
  42. User user2 = new User(2, 12);
  43. User user3 = new User(3, 10);
  44. User[] users = { user1, user2, user3};
  45. Arrays.sort(users);
  46. Arrays.stream(users).forEach(System.out::println);
  47. }
  48. }

int compareTo(T o)

比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

参数: o - 要比较的对象。

返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。

抛出:ClassCastException - 如果指定对象的类型不允许它与此对象进行比较

Comparator

Comparator接口在JDK8中的源码:

  1. package java.util;
  2. import java.io.Serializable;
  3. import java.util.function.Function;
  4. import java.util.function.ToIntFunction;
  5. import java.util.function.ToLongFunction;
  6. import java.util.function.ToDoubleFunction;
  7. import java.util.Comparators;
  8. public interface Comparator<T> {
  9. int compare(T o1, T o2);
  10. //还有很多其他方法...
  11. }

使用:

  1. public class Child {
  2. private Integer id;
  3. private Integer age;
  4. public Child() {
  5. }
  6. public Child(Integer id, Integer age) {
  7. this.id = id;
  8. this.age = age;
  9. }
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setId(Integer id) {
  14. this.id = id;
  15. }
  16. public Integer getAge() {
  17. return age;
  18. }
  19. public void setAge(Integer age) {
  20. this.age = age;
  21. }
  22. @Override
  23. public String toString() {
  24. return "Child{" +
  25. "id=" + id +
  26. ", age=" + age +
  27. '}';
  28. }
  29. }
  30. public class Test {
  31. public static void main(String[] args) {
  32. Child child1 = new Child(1, 14);
  33. Child child2 = new Child(2, 12);
  34. Child child3 = new Child(3, 10);
  35. List<Child> list = new ArrayList<>();
  36. list.add(child1);
  37. list.add(child2);
  38. list.add(child3);
  39. Collections.sort(list, new Comparator<Child>() {
  40. @Override
  41. public int compare(Child o1, Child o2) {
  42. return o1.getAge() > o2.getAge() ? 1 : (o1.getAge() == o2.getAge() ? 0 : -1);
  43. }
  44. });
  45. // 或者使用JDK8中的Lambda表达式
  46. //Collections.sort(list, (o1, o2) -> (o1.getAge()-o2.getAge()));
  47. list.stream().forEach(System.out::println);
  48. }
  49. }

或者也可以通过实现的方式使用Comparator接口:

  1. import java.util.Comparator;
  2. public class Child implements Comparator<Child> {
  3. private Integer id;
  4. private Integer age;
  5. public Child() {
  6. }
  7. public Child(Integer id, Integer age) {
  8. this.id = id;
  9. this.age = age;
  10. }
  11. @Override
  12. public int compare(Child o1, Child o2) {
  13. return o1.getAge() > o2.getAge() ? 1 : (o1.getAge() == o2.getAge() ? 0 : -1);
  14. }
  15. public Integer getId() {
  16. return id;
  17. }
  18. public void setId(Integer id) {
  19. this.id = id;
  20. }
  21. public Integer getAge() {
  22. return age;
  23. }
  24. public void setAge(Integer age) {
  25. this.age = age;
  26. }
  27. @Override
  28. public String toString() {
  29. return "Child{" +
  30. "id=" + id +
  31. ", age=" + age +
  32. '}';
  33. }
  34. }
  35. public class Test {
  36. public static void main(String[] args) {
  37. Child child1 = new Child(1, 14);
  38. Child child2 = new Child(2, 12);
  39. Child child3 = new Child(3, 10);
  40. List<Child> list = new ArrayList<>();
  41. list.add(child1);
  42. list.add(child2);
  43. list.add(child3);
  44. Collections.sort(list, new Child());
  45. list.stream().forEach(System.out::println);
  46. }
  47. }

Comparator接口其他默认方法的用法

reversed方法

  1. default Comparator<T> reversed() {
  2. return Collections.reverseOrder(this);
  3. }

这个方法是用来生成一个逆序器,比如我们开始需要得到一个正序的排序序列,然后又想得到一个反转的排序序列,就可以使用该方法。比如:

  1. public class Test {
  2. public static void main(String[] args) {
  3. Child child1 = new Child(1, 14);
  4. Child child2 = new Child(2, 12);
  5. Child child3 = new Child(5, 10);
  6. Child child4 = new Child(4, 10);
  7. List<Child> list = new ArrayList<>();
  8. list.add(child1);
  9. list.add(child2);
  10. list.add(child3);
  11. list.add(child4);
  12. Comparator<Child> comparator = Comparator.comparingInt(x -> x.getAge());
  13. Collections.sort(list, comparator);
  14. list.stream().forEach(System.out::println);
  15. Collections.sort(list, comparator.reversed());
  16. list.stream().forEach(System.out::println);
  17. }
  18. }

thenComparing

  1. default <U extends Comparable<? super U>> Comparator<T> thenComparing(
  2. Function<? super T, ? extends U> keyExtractor)
  3. {
  4. return thenComparing(comparing(keyExtractor));
  5. }

该方法是在原有的比较器上再加入一个比较器,比如先按照年龄排序,年龄相同的在按照id排序。比如:

  1. public class Test {
  2. public static void main(String[] args) {
  3. Child child1 = new Child(1, 14);
  4. Child child2 = new Child(2, 12);
  5. Child child3 = new Child(5, 10);
  6. Child child4 = new Child(4, 10);
  7. List<Child> list = new ArrayList<>();
  8. list.add(child1);
  9. list.add(child2);
  10. list.add(child3);
  11. list.add(child4);
  12. Comparator<Child> comparator = Comparator.comparingInt(x -> x.getAge());
  13. Collections.sort(list, comparator);
  14. list.stream().forEach(System.out::println);
  15. System.out.println("-----");
  16. Collections.sort(list, comparator.thenComparing(x->x.getId()));
  17. list.stream().forEach(System.out::println);
  18. }
  19. }

Comparable接口和Comparator接口的区别

  • Comparable接口位于java.lang包下;Comparator位于java.util包下
  • Comparable接口只提供了一个compareTo()方法;Comparator接口不仅提供了compara()方法,还提供了其他默认方法,如reversed()、thenComparing(),使我们可以按照更多的方式进行排序
  • 如果要用Comparable接口,则必须实现这个接口,并重写comparaTo()方法;但是Comparator接口可以在类外部使用,通过将该接口的一个匿名类对象当做参数传递给Collections.sort()方法或者Arrays.sort()方法实现排序。Comparator体现了一种策略模式,即可以不用要把比较方法嵌入到类中,而是可以单独在类外部使用,这样我们就可有不用改变类本身的代码而实现对类对象进行排序。

发表评论

表情:
评论列表 (有 0 条评论,187人围观)

还没有评论,来说两句吧...

相关阅读