一、构造器引用
和方法引用类似,只不过方法名为new,如Interval::new就是Interval的构造器引用。
也可以用数组类型的构造引用,如int[]::new,它等价于 x->new int[x],一个参数指定数组大小。
构造引用可以为构造泛型数组提供方便,Java规定无法构造类型为T的数组,因为表达式new T[n]会被翻译成new Object[n]。例如,List<T>的toArray()方法只能返回Object数组,使用构造引用可以直接返回T类型的数组:
Interval[] intervalArray = list.toArray(Interval[]::new);
二、Comparator
至此,实现函数式接口的三种方法已介绍完毕,它们分别是:lambda表达式、方法引用和构造引用,虽然这是三种不同的类型,但是功能和lambda表达式等价。
接下来回到问题的开始:为了将Interval实现为可比较类引入了Comparator,之后才延伸出内部匿名类、lambda表达式、函数式接口等概念,现在已经可以对使用Comparator进行数组排序这一问题做出一些扩展了。
(1) Comparator.comparing
comparing是Comparator的一个工厂方法,它需要一个“键提取器”函数作为参数,将类型T映射为一个可比较类型,例如,可以将最初的对Interval列表排序的语句重新实现为:
Collections.sort(list, Comparator.comparing(Interval::getStart));
因为Interval.getStart的返回值是Long类型,所以这个Comparator的compare方法也默认是Long.compare。若想要使用其它比较器,可以在comparing的第二个参数上指定,如有一个Person类,现要按FirstName的长度对Person列表排序,就可以用lambda表达式自定义比较器。
Collections.sort(people,
Comparator.comparing(Person::getFirstName, (s1, s2) -> Integer.compare(s1.length(), s2.length())));
(2) thenComparing
有时需要处理比较相等的情况,如两个人的FirstName相同时,希望使用LastName再次比较作为比较结果,这时就可以使用thenComparing方法:
Collections.sort(people, Comparator.comparing(Person::getFirstName).thenComparing(Person::getLastName));
三、小结
本文简要介绍了使用构造器引用实现函数式接口的方法,对使用Comparator排序列表的问题做出了一些扩展。