一、Lambda的底层运行原理
首先,创建一个LambdaDemo.java文件编写如下的代码(代码示例1),通过javac命令编译LambdaDemo.java,则得到LambdaDemo.class和FunctionalDemo.class字节码文件, 通过java -Djdk.internal.lambda.dumpProxyClasses LambdaDemo命令运行代码,又会多出一个LambdaDemo$$Lambda$1.class文件,再通过javaP - p命令分别反编译 LambdaDemo.class和LambdaDemo$$Lambda$1.class字节码文件得到示例2的代码。
代码示例1:
public class LambdaDemo { public static void main(String[] args) { FunctionalDemo functionalDemo = s -> System.out.println(s); functionalDemo.test("λ表达式"); } }
@FunctionalInterface interface FunctionalDemo { void test(String s); }
代码示例2:
PS D:setupsamples> javap -p '.LambdaDemo.class' Compiled from "LambdaDemo.java" public class LambdaDemo { public LambdaDemo(); public static void main(java.lang.String[]); private static void lambda$main$0(java.lang.String); } PS D:setupsamples> javap -p '.LambdaDemo$$Lambda$1.class' final class LambdaDemo$$Lambda$1 implements FunctionalDemo { private LambdaDemo$$Lambda$1(); public void test(java.lang.String); } PS D:setupsamples>
可以发现Lambda表达式在编译过程中,首先对FunctionalDemo接口进行实现生成了实现类LambdaDemo$$Lambda$1,之后,在LambdaDemo类中会生成一个私有静态方法lambda$main$0,然后lambda$main$0方法调用实现类LambdaDemo$$Lambda$1中的test方法完成Lambda表达式中的内容。
所以综上:
1.Lambda在JVM底层被解释成私有静态方法和匿名内部类型。
2.通过静态实现方法调用实现接口的匿名内部类中接口方法,完成Lambda表达式的执行。
二、Stream的Api简介
stream的Api是JDK8提供的数据存储类操作API,配合Lambda表达式可以极大的简化集合操作,提高代码质量,且支持串行、并行操作,一个Stream实例只能被使用一次。特点:stream不会影响原有的数据存储对象,会生成一个新的数据存储对象,所以对于stream有中间操作和结束操作,中间操作指对数据进行比较过滤等,结束操作指将最终的结果输出。常见的中间操作有map/filter等,结束操作有foreach/collect/max/min等,中间操作是lazy操作,并不会立即执行,只会在结束操作确认后执行。
1. 数组集合获取Stream实例的方式
(1)数组:Arrays.stream(T[] Arrays)
(2)List和Set:List.stream()、Set.stream()
(3)Map: Map.entrySet.stream()
2. filter操作:根据条件过滤
3. map操作:遍历并返回
4. max/min操作: 根据条件比较出最大最小
代码示例3:
import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class LambdaDemo { public static void main(String[] args) { List<User> users = new ArrayList<>(); users.add(new User("李白", 26)); users.add(new User("李商隐", 23)); users.add(new User("杜甫", 18)); users.add(new User("杜牧", 9)); /*foreach遍历*/ users.stream().forEach(user -> System.out.println(user.getName())); /*map操作*/ users.stream().map(user -> user.getAge()).collect(Collectors.toList()).forEach(name-> { System.out.println(name); }); /*filter操作*/ users.stream().filter(user -> user.getAge() < 20).forEach(user -> System.out.println(user.getName())); /*max操作,min操作相似*/ String name = users.stream().max((user1, user2) -> user1.getAge() - user2.getAge()).get().getName(); System.out.println(name); //lambda对于内部方法的引用可简化为以下 // Optional<User> max = users.stream().max(Comparator.comparingInt(User::getAge)); } } class User { public User(String name, Integer age) { this.name = name; this.age = age; } private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }