函数
将方法 变成 值 进行传递
方法引用
方法可以作为值传递,将方法作为值传递在Java8中被实现,它的语法是:::
,它的名称叫:方法引用。
类名::方法名
代码示例
Apple 类
属性:
- weight:重量
- color:颜色
方法:
isGreenApple
,判断这个苹果是否是绿色isHeavyApple
,判断这个苹果是否很重(重量 > 150)
public class Apple {
private int weight = 0;
private String color = "";
public Apple(int weight, String color){
this.weight = weight;
this.color = color;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String toString() {
return "Apple{" +
"color='" + color + '\'' +
", weight=" + weight +
'}';
}
public static boolean isGreenApple(Apple apple){
return "green".equals(apple.getColor());
}
public static boolean isHeavyApple(Apple apple){
return apple.getWeight() > 150;
}
}
GetApple
使用 Java8 的新特性,通过函数引用,来筛选数组
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class GetApple {
public static void main(String[] args) {
List<Apple> appleList = new ArrayList<>();
appleList.add(new Apple(152,"green"));
appleList.add(new Apple(30,"green"));
appleList.add(new Apple(155,"red"));
// 获取到 appleList 中是绿色的所有苹果
List<Apple> appleList1 = filterGreenApples(appleList, Apple::isGreenApple);
// 获取到 appleList 中超重( > 150)的所有苹果
List<Apple> appleList2 = filterGreenApples(appleList, Apple::isHeavyApple);
System.out.println("输出所有的绿色苹果");
for (Apple apple : appleList1) {
System.out.println(apple);
}
System.out.println("输出所有的大苹果,重量大于 150");
for (Apple apple : appleList2) {
System.out.println(apple);
}
}
public static List<Apple> filterGreenApples(List<Apple> inventory, Predicate<Apple> predicate){
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (predicate.test(apple)){
result.add(apple);
}
}
return result;
}
}
Predict
可以将方法用值进行传递,用 Predict 接收对应的方法,然后使用
Predict.test()
即可实现传入的参数是否通过这个测试。
Apple::isGreenApple
Predicate<Apple>
Lambda表达式
如果没有方便的方法和类可用的话可以使用 Lambda表达式 或者再说:类似于
isHeavyApple
和isGreenApple
这种可能只用一两次的短方法写一堆定义有点儿烦人,这会可以使用Lambda 表达式,下面是一个 Lambda 表达式的示例:
(int x) -> x + 1
我们使用 Lambda 表达式来改写上述的GetApple
代码,也就是13
行,和16
行代码
// 获取到 appleList 中是绿色的所有苹果
List<Apple> appleList1 = filterGreenApples(appleList, (Apple a) -> "green".equals(a.getColor()));
// 获取到 appleList 中超重( > 150)的所有苹果
List<Apple> appleList2 = filterGreenApples(appleList, (Apple a) -> a.getWeight() > 150);
然后,可以将 Apple
中的33
行代码,以及37
行代码进行删除。
如果这个方法只是被临时调用一次,而在其它地方不会再掉调用了,可以使用 Lambda 表达式,该表达式非常适合定义只用一次的方法。
上面两种方法的输出结果:
输出所有的绿色苹果
Apple{color='green', weight=152}
Apple{color='green', weight=30}
输出所有的大苹果,重量大于 150
Apple{color='green', weight=152}
Apple{color='red', weight=155}
Stream 流
现在我们要对GetAplle
中的filterGreenApples
出手了,也就是代码的29
行,我们可以使用Stream
流进行优化。
介绍
Java应用都会制造和处理集合。但集合用起来并不总是那么理想。现在使用流的方式,可以将实际编码进行抽象,极大的降低复杂集合的逻辑处理。
代码示例:从一个列表中筛选金额较高的交易,然后按货币分组。
上述的代码存在一个问题:可读性差;如果通过 Stream 流的方式,将会是这个样子:
这个例子,仅仅用来感叹一下stream
流对代码进行了抽象后,代码变得:
使用 Stream 改写我们的代码
现在我们将原本的逻辑再复制一下:
public static List<Apple> filterGreenApples(List<Apple> inventory, Predicate<Apple> predicate){
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (predicate.test(apple)){
result.add(apple);
}
}
return result;
}
这个逻辑的核心就是:对集合再计算
Ok,Stream 流的核心优点出现:计算,它能简化计算的逻辑,与其说是简化不如说是抽象成思维,现在改写这个逻辑,并且结合 Lambda 表达式
,代码结果如下:
List<Apple> collect = appleList
.stream()
.filter((Apple apple) -> "green".equals(apple.getColor()))
.collect(toList());
- 首先要将
Collect
转换成 流,使用的是.stream()
方法 - 接下去就是计算操作,这里以
.filter()
为例,可见:filter()
中接收一个参数,而这个参数就是Predict
类型的,它用来接收一个方法引用,而这个方法引用可以使用::
或者Lambda 表达式
传入。
collect(toList())
这里暂时略过,这里就知道是将上一步的结果封装成一个 List 即可。
输出上述的结果:
Apple{color='green', weight=152}
Apple{color='green', weight=30}