Java Comparator接口学习笔记

匿名 (未验证) 提交于 2019-12-02 20:41:15

Comparator是一个泛型函数式接口T表示待比较对象的类型

@FunctionalInterface public interface Comparator<T> { }

唯一的非Object抽象方法: compare

int compare(T o1, T o2)

根据o1, o2的大小关系返回:负数、0、正数

其比较逻辑依赖于赋值给Comparator类型变量的Lambda表达式、Comparator对象等:

Comparator<String> comparator = Comparator.comparingInt(String::length); // 比较String类对象的length System.out.println(comparator.compare("Tom", "Jerry")); // -1

// 源码1 public static <T, U extends Comparable<? super U>> Comparator<T> comparing(     Function<? super T, ? extends U> keyExtractor) {     Objects.requireNonNull(keyExtractor);     return (Comparator<T> & Serializable)         (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); }
  • 返回值:comparing返回一个T类型的Comparator对象(也就是用于比较T类型对象的Comparator

  • 参数:comparing的参数是一个Function类型,它接收T类型及T的超类型, 返回U类型及U的子类型。keyExtractor用Lambda表达式实现

    例如,输入String,提取其长度:

    Comparator<String> keyComparator = Comparator.comparing(String::length); keyComparator.compare("Tom", "Jerry");
  • 函数体:
    • 首先,确保keyExtractor不是null
    • 然后,返回一个Lambda表达式,该表达式对c1c2提取出来的key进行比较 (用的是c1c2类实现的compareTo()进行比较)
public static <T, U> Comparator<T> comparing(     Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) {     Objects.requireNonNull(keyExtractor);     Objects.requireNonNull(keyComparator);     return (Comparator<T> & Serializable)         (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),                                           keyExtractor.apply(c2)); }

与上面类似,只不过将key的比较逻辑由compareTo()替换成了自定义的比较逻辑

实例:

package Lambda.ComparatorDemo;  import java.util.Arrays; import java.util.Comparator;  class Person {     private String fname;     private String lname;      public Person(String fname, String lname) {         this.fname = fname;         this.lname = lname;     }      public String getFname() {         return fname;     }      public String getLname() {         return lname;     }      @Override     public String toString() {         return fname + " " + lname;     } }  public class ComparingDemo {     public static void main(String[] args) {         Person p1 = new Person("Tom", "Kenn");         Person p2 = new Person("Alice", "Zed");         Person[] persons1 = {p1, p2};         Person[] persons2 = persons1.clone();          // 依据First Name排序(用的是String类的compareTo的比较逻辑)         Arrays.sort(persons1, Comparator.comparing(Person::getFname));         System.out.println("Person1 (Sorted by first name): ");         for (Person p : persons1) {             System.out.println(p);         }          System.out.println();          // 依据First Name的长度排序         Arrays.sort(persons2, Comparator.comparing(Person::getFname, Comparator.comparingInt(String::length)));         System.out.println("Person2 (Sorted by length of first name):");         for (Person p : persons2) {             System.out.println(p);         }     } } 
  • comparingInt()
  • comparingDouble()
  • comparingLong()

comparing是一样的思路,只不过comparingXXX()comparing中的提取出来的key类型固定为了XXX

public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {         Objects.requireNonNull(keyExtractor);         return (Comparator<T> & Serializable)             (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1),                                       keyExtractor.applyAsInt(c2));     }

thenComparing是默认方法,需要对具体的Comparator对象调用,它用于将多个Comparator结合起来实现“链式的比较”:先根据XXX比较,再根据XXX比较,...

// 源码 default Comparator<T> thenComparing(Comparator<? super T> other) {     Objects.requireNonNull(other);     return (Comparator<T> & Serializable) (c1, c2) -> {         int res = compare(c1, c2);         return (res != 0) ? res : other.compare(c1, c2);     }; }
public class thenComparingDemo {     public static void main(String[] args) {         Person p1 = new Person("Alice", "Jessy");         Person p2 = new Person("Alice", "Ann");         Person p3 = new Person("Tom", "Smith");          Person[] persons = {p1, p2, p3};          // 先根据first name比较,再根据last name的长度比较         Comparator<Person> chainedComparator = Comparator.comparing(Person::getFname)                 .thenComparing((x, y) -> (x.getLname().length() - y.getLname().length()));                   // 先根据first name排序,再根据last name的长度排序         Arrays.sort(persons, chainedComparator);         for (Person p : persons) {             System.out.println(p);         }     } }  /* Alice Ann Alice Jessy Tom Smith

参考:

https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#thenComparing-java.util.Comparator

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!