Java专题-lambda和stream

133 阅读3分钟

segmentfault.com/a/119000002…

ifeve.com/jvm%e4%b9%8…

什么是Lambda

Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

Lambda 表达式描述了一个代码块(或者叫匿名方法),可以将其作为参数传递给构造方法或者普通方法以便后续执行

函数式接口

@FunctionalInterface修饰 的接口,有且只有一个抽象方法

语法

参数列表 -> 代码主体

  1. 表达式-风格

    (parameters) -> expression

  2. 块-风格

    (parameters) -> { statements; }

常用函数式接口

随Lambda一同增加的还有一个java.util.function包,其中定义了一些常见的函数式接口的。比如:

  • Function,接受一个输入参数,返回一个结果。参数与返回值的类型可以不同,我们之前的map方法内的lambda就是表示这个函数式接口的;
  • Consumer,接受一个输入参数并且无返回的操作。比如我们针对数据流的每一个元素进行打印,就可以用基于Consumer的lambda;
  • Supplier,无需输入参数,只返回结果。看接口名就知道是发挥了对象工厂的作用;
  • Predicate,接受一个输入参数,返回一个布尔值结果。比如我们在对数据流中的元素进行筛选的时候,就可以用基于Predicate的Lambda;

方法引用

当在Lambda表达式中直接调用了一个方法时可以使用,其写法为目标引用::方法名称

  1. 指向静态方法的方法引用

    Function<String, Integer> fun = s -> Integer.parseInt(s);
    Function<String, Integer> fun = Integer::parseInt;
    
  2. 指向任意类型实例方法的方法引用

    Function<String, Integer> fun = s -> s.length();
    Function<String, Integer> fun = String::length;
    
  3. 指向现存外部对象实例方法的方法引用

    String s = "hello";
    Supplier<Integer> len = () -> s.length();
    Supplier<Integer> len = s::length;
    

实现原理

lambda实质是对象引用

表明上看是一个实现了接口的匿名类

1.生成一个私有的静态函数,函数中执行表达式里的内容

2.javap -v 生成字节码,看到底层使用了invokedynamic指令,动态调用对应上面的静态方法

常见的方法调用字节码

image.png

Stream原理

blog.csdn.net/cxiaoxifeng…

基本原理

Stream流计算分为三步,第一步生成流,即入口;

第二步对流中的数据进行操作,也就是中间操作

第三步返回数据,也就是结束操作。每个流至少有一个入口和一个结束操作,可以有零个或多个中间操作。需要说明的是第二步中的中间操作不是实时进行,是滞后的,等遇到结束操作的时候会执行

因此stream是惰性的,所有中间操作都是由结束操作触发的。

操作

Stream中的操作可以分为两大类:中间操作与结束操作,中间操作只是对操作进行了记录,只有结束操作才会触发实际的计算(即惰性求值),这也是Stream在迭代大集合时高效的原因之一。 中间操作又可以分为无状态(Stateless)操作与有状态(Stateful)操作,前者是指元素的处理不受之前元素的影响;后者是指该操作只有拿到所有元素之后才能继续下去。 结束操作又可以分为短路与非短路操作,这个应该很好理解,前者是指遇到某些符合条件的元素就可以得到最终结果;而后者是指必须处理所有元素才能得到最终结果。

Stream操作分类

Stream操作分类状态方法
中间操作(Intermediate operations)无状态(Stateless)unordered() filter() map() mapToInt() mapToLong() mapToDouble() flatMap() flatMapToInt() flatMapToLong() flatMapToDouble() peek()
中间操作(Intermediate operations)有状态(Stateful)distinct() sorted() sorted() limit() skip()
结束操作(Terminal operations)非短路操作forEach() forEachOrdered() toArray() reduce() collect() max() min() count()
结束操作(Terminal operations)短路操作(short-circuiting)anyMatch() allMatch() noneMatch() findFirst() findAny()
AbstractPipeline

AbstractPipeline中定义了三个AbstractPipeline类型的变量:sourceStage(源阶段),previousStage(上游pipeline,前一阶段),nextStage(下一阶段)。