初识:Stream流及Lambda表达式

98 阅读3分钟

函数

方法 变成 进行传递

方法引用

方法可以作为值传递,将方法作为值传递在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表达式 或者再说:类似于isHeavyAppleisGreenApple这种可能只用一两次的短方法写一堆定义有点儿烦人,这会可以使用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应用都会制造和处理集合。但集合用起来并不总是那么理想。现在使用流的方式,可以将实际编码进行抽象,极大的降低复杂集合的逻辑处理。

代码示例:从一个列表中筛选金额较高的交易,然后按货币分组。
image.png
上述的代码存在一个问题:可读性差;如果通过 Stream 流的方式,将会是这个样子:
image.png
这个例子,仅仅用来感叹一下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());
  1. 首先要将Collect转换成 流,使用的是.stream()方法
  2. 接下去就是计算操作,这里以.filter()为例,可见:filter()中接收一个参数,而这个参数就是Predict类型的,它用来接收一个方法引用,而这个方法引用可以使用::或者Lambda 表达式传入。

image.png

  1. collect(toList())这里暂时略过,这里就知道是将上一步的结果封装成一个 List 即可。

输出上述的结果:

Apple{color='green', weight=152}
Apple{color='green', weight=30}

tips 多线程

Stream 流开启多线程执行,只需要将stream()改写成parallelStream()