今天在学习Java核心技术集合程序清单9-3时遇到了问题。 代码如下
public class TreeSetTest { public static void main(String[] args) { SortedSet<Item> parts = new TreeSet<>(); parts.add(new Item("Toaster", 1234)); parts.add(new Item("Widget", 4562)); parts.add(new Item("Modem", 9912)); System.out.println(parts); NavigableSet<Item> sortByDescription = new TreeSet<Item>(Comparator.comparing(Item::getDescription)); sortByDescription.addAll(parts); System.out.println(sortByDescription); } }
public class Item implements Comparable<Item>{ private String description; private int partNumber; public Item(String aDescroption,int aPartNumber) { description = aDescroption; partNumber = aPartNumber; } public String getDescription() { return description; } public String toString() { return "[description=" + description + ",partNumber=" + partNumber + "]"; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Item other = (Item)obj; return Objects.equals(description, other.description) && partNumber == other.partNumber; } public int hasCode() { return Objects.hash(description,partNumber); } @Override public int compareTo(Item o) { int diff = Integer.compare(partNumber,o.partNumber); return diff != 0 ? diff : description.compareTo(o.description); } }
可以看到,在主函数中定制了一个比较器来按照描述信息排序,在看这个比较器定义的源码时有些看不懂,所以回去查阅了关于lambda表达式、泛型等知识,在这里记录以下以便以后查阅
首先看源码
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)); }
在这里涉及到的知识点在下面一一解析
1,泛型
U extends Comparable<? super U>
在这里表示 U实现了Comparable接口,同时Comparable接口中的实例域是U的父类。
带有超类型super限定的通配符表示了域的下限,即可以接收U的超类的作为Comparable中参数的类型
带有子类型extends限定的通配符表示了U的上限,即U只能是实现了Comparable接口的子类。
2,函数式接口。 函数式接口是用来接收函数作为参数的,用于lambda
这里的Function是一个函数式接口,是Java给出的,表示有一个T类型参数的函数。原型是
Function<T,R>
T是参数类型,R是返回类型。Function接口自带一个apply方法,R apply(T) ,表示由T参数得到R的返回。
3,这里参数传入的是Item::getDescription,对应函数式接口Function,该函数的返回值String类型对应T,所以源码中的comparaTo对应的是String.comparaTo (String实现了Comparable)
所以这个比较器的结果也应当是按照字典顺序排序的。