如果我们要对苹果集合按照重量进行排序,使用我们前面已学的lambda要怎么写呢?
苹果集合
List apples = new ArrayList<>(); Apple a1 = new Apple("红",155); Apple a2 = new Apple("绿",136); Apple a3 = new Apple("红",169); apples.add(a1); apples.add(a2); apples.add(a3);
要对这个苹果集合按照重量由轻到重排序,如何写?
首先要知道List本身提供了sort方法,方法需要传入一个Comparator的实现,用做排序逻辑,我们写一个lambda就可以了,不用再像以前写一个实现类或者匿名类。
System.out.println("---排序前---");apples.forEach(System.out::println);apples.sort((Apple a11, Apple a22) -> a11.getWeight() <= a22.getWeight()?-1:1);System.out.println("---排序后---");apples.forEach(System.out::println);
输出结果:
---排序前---Apple(color=红, weight=155)Apple(color=绿, weight=136)Apple(color=红, weight=169)---排序后---Apple(color=绿, weight=136)Apple(color=红, weight=155)Apple(color=红, weight=169)
这是我们运用前面几节学到的知识,写出的lambda表达式实现了排序功能。
在Java8中,一个新特性就是可以直接引用一个类的普通方法,这种用法叫做:方法引用。
运用方法引用,我们将上面的排序进行一些改造:
System.out.println("---排序前---");apples.forEach(System.out::println);apples.sort(Comparator.comparing(Apple::getWeight).reversed());System.out.println("---排序后---");apples.forEach(System.out::println);
输出结果:
---排序前---Apple(color=绿, weight=136)Apple(color=红, weight=155)Apple(color=红, weight=169)---排序后---Apple(color=红, weight=169)Apple(color=红, weight=155)Apple(color=绿, weight=136)
一个类中的普通成员方法,使用方法引用的方式调用写入是:
类名::方法名
类名和方法名中间有两个冒号。
上面的例子中,Comparator.comparing(Apple::getWeight),使用了Comparator类提供的comparing方法,方法参数是:Apple::getWeight,是不是有点不可思议,先看一下comparing方法的源码;
public static > Comparator comparing( Function super T, ? extends U> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); }
我们可以看到最重要的一行:
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2))
其实这还是我们第一种写法,只不过,通过方法引用,进行了简化,相当于一个语法糖,在源码中,还是需要两个参数,来进行比较,而参数keyExtractor,则可以转化为:c1.getWeight().compareTo.c2.getWeight()。
源码中的:
keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2))
可以转化为:
c1.getWeight().compareTo.c2.getWeight()
其实就是这样的效果,这也就是我们前面所说的:行为参数化。我们的参数是一个getWeight()的行为,而不是像传统方法,c1.getWeight()=155,拿这个155当作参数,传入方法。
在本文的第二个例子中:
Comparator.comparing(Apple::getWeight).reversed()
我们最后还用到了reversed(),相当于是对排序结果反转。
方法引用,并不仅仅是上面这一种使用方法,主要由以下几种: