官方介绍:Lambda expressions are a new and important feature included in Java SE 8. They provide a clear and concise way to represent one method interface using an expression. Lambda expressions also improve the Collection
libraries making it easier to iterate through, filter, and extract data from a Collection
. In addition, new concurrency features improve performance in multicore environments。
函数编程在C#、Python、JavaScript中都得到充分体现。而Java直到最新的Java 8才开始正式支持函数编程,最明显的改进就是对Lambda表达式的支持。正如C#之父Anders Hejlsberg在那篇文章《编程语言大趋势》中所讲,未来的编程语言将逐渐融合各自的特性,而不存在单纯的声明式语言(如之前的Java)或者单纯的函数编程语言。将来声明式编程语言借鉴函数编程思想,函数编程语言融合声明式编程特性...这几乎是一种必然趋势。
HotSpot 实现
Lambda 不只是可以减少很多代码的编写,其字节码和运行时的实现也比 Java 7 中的匿名类的效率更高。针对每一个 Lambda 表达式,编译器都会创建一个对应的形如 Lambda$1() 这样的方法。这个过程被称之为 Lambda body desugaring. 当遇见一个 Lambda 表达式,编译器将会发起一个 invokedynamic 调用,并从目标功能接口中获取返回值。
一、java为什么需要Lambda表达式
1、更方便地遍历、过滤、操作集合中的数据,可以并行处理,充分利用多核CPU的优势,有利于JIT编译器对代码进行优化:
例如:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.forEach((Integer value) -> System.out.println(value));
2、传递行为,而不仅仅是传值:
例如:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
List<String> filteredNames = names.stream().filter(e -> e.length() >= 4).collect(Collectors.toList());
filteredNames.forEach((String value) -> System.out.println(value));
Stream.reduce,常用的方法有average, sum, min, max, and count,返回单个的结果值,并且reduce操作每处理一个元素总是创建一个新值。Stream.collection与stream.reduce方法不同,Stream.collect修改现存的值,而不是每处理一个元素,创建一个新值。其实上述stream的很多操作都是基于java.util.function包中的接口来实现的。例如Predicate用来实filter,Supplier用来实现collect。
二、Lambda表达式中的stream的生成
stream的生成主要有2种方式:
1、通过collection接口的stream方法生成
例如:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream<Integer> stream = numbers.stream();
2、通过Stream类的静态方法创建
例如:生成斐波那契数列
class FibonacciSupplier implements Supplier<Long> {
long a = 0;
long b = 1;
@Override
public Long get() {
long x = a + b;
a = b;
b = x;
return a;
}
}
public class FibonacciStream {
public static void main(String[] args) {
Stream<Long> fibonacci = Stream.generate(new FibonacciSupplier());
fibonacci.limit(10).forEach(System.out::println);
}
}
三、使用Lambda表达式编写函数式接口
函数式接口是指只包含一个方法的接口,比如runnable、comparable、Listener等。比如注册监听器、比较2个集合内的元素,我们通常会写一个内部类并实现一个方法来达到目的,而Lambda却可以简化其中的大部分代码而达到同样的目的。例如:
Runnable Lambda
public class RunnableTest { 1 public static void main(String[] args) { 2 3 System.out.println("===RunnableTest==="); 4 5 //AnonymousRunnable 6 Runnable r1 = new Runnable(){ 7 8 @Override 9 public void run(){ 10 System.out.println("Helloworldone!"); 11 } 12 }; 13 14 //LambdaRunnable 15 Runnable r2 = () -> System.out.println("Helloworldtwo!"); 16 17 //Runem! 18 r1.run(); 19 r2.run(); 20 21 } 22 }
Comparator Lambda
14 public class ComparatorTest { 15 16 public static void main(String[] args) { 17 18 List<Person> personList = Person.createShortList(); 19 20 //SortwithInnerClass 21 Collections.sort(personList, new Comparator<Person>(){ 22 public int compare(Person p1, Person p2){ 23 return p1.getSurName().compareTo(p2.getSurName()); 24 } 25 }); 26 27 System.out.println("===SortedAscSurName==="); 28 for(Person p:personList){ 29 p.printName(); 30 } 31 32 //UseLambdainstead 33 34 //PrintAsc 35 System.out.println("===SortedAscSurName==="); 36 Collections.sort(personList, (Person p1, Person p2) -> p1.getSurName().compareTo(p2.getSurName())); 37 38 for(Person p:personList){ 39 p.printName(); 40 } 41 42 //PrintDesc 43 System.out.println("===SortedDescSurName==="); 44 Collections.sort(personList, (p1, p2) -> p2.getSurName().compareTo(p1.getSurName())); 45 46 for(Person p:personList){ 47 p.printName(); 48 } 49 50 } 51 }
Listener Lambda
JButton testButton = new JButton("TestButton"); 17 testButton.addActionListener(new ActionListener(){ 18 @Override public void actionPerformed(ActionEvent ae){ 19 System.out.println("ClickDetectedbyAnonClass"); 20 } 21 }); 22 23 testButton.addActionListener(e -> System.out.println("ClickDetectedbyLambdaListner"));