什么是Lambda
lambda表达式是java提供的一种语法糖,我理解的语法糖就是简洁编码形式,比如,增强for这个语法糖就是普通for循环的简洁形式。lambda采用函数式编程来简化java代码的编写。
语法
参数,箭头(->) 以及一个表达式或语句块。本质上lambda表达式是一种匿名方法。下面是一个lambda的例子
public int add(int x, int y) {
return x * y;
}
转成λ表达式后是这个样子:
(int x, int y) -> x * y;
参数类型也可以省略,Java编译器会根据上下文推断出来:
(x, y) -> x * y;
如果是无参函数,且无返回值,参数列表的括号要保留
()->{System.out.println("你好")};
什么时候可以使用lambda?
对于只有一个抽象方法的接口,这种接口称为函数式接口。在需要这种接口对象的地方,可以提供一个lambda表达式。在jdk1.8之前,在需要函数式接口对象的地方,我们通常提供一个匿名内部类。1.8之后,lambda表达式常常用于替代匿名内部类。
下面是几种常见的函数式接口:
@FunctionalInterface
public interface Runnable { void run(); }
public interface Callable<V> { V call() throws Exception; }
public interface ActionListener { void actionPerformed(ActionEvent e); }
public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }
//这里equals是Object的方法
lambda与匿名内部类的比较
这里run方法无参数,无返回值,所以lambda表达式中参数为空,表达式无返回值。
@Test
public void test(){
//old
new Thread((new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类 实现线程");
}
})).start();
//lambda
new Thread( () -> System.out.println("java8 lambda实现线程")).start();
}
Arrays.sort(a, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
//lambda表达式写法
Arrays.sort(a,(o1,o2)->return o2.compareTo(o1);)
lambda之集合操作
list.forEach(o -> {System.out.println(o);});
方法引用
可以直接把方法引用传递到需要函数式接口的地方。比如
list.forEach(System.out::println);
方法引用要用 :: 操作符分隔类名与方法名,一般有三种形式:
//对象的实例方法,比如System.out::println等价于e -> System.out.println(e);
object::instanceMethod;
//类的静态方法,Math::pow等价于(x,y)->Math.pow(x,y);
Class::staticMethod;
//类的实例方法,比如String::compareToIgnoreCase等价于(x,y)->x.compareToIgnoreCase(y);
Class::instanceMethod;
还有一种构造器引用,比如Person::new等价于p->new Person();
在第二第三种情况中,一般针对final修饰的类。在第三种情况中,第一个参数又称为方法的目标。此处方法引用等同于lambda表达式,可以放在需要函数式接口实例的地方。
Lambda表达式变量作用域
lambda表达式中可以访问外围方法或类中的变量,但是在lambda中只能引用值不会改变的变量。如果lambda中外部变量的值在外部变化,或者在lambda中改变,都是不合法的。之所以有这个限制是因为如果在lambda中改变变量,并发执行会不安全。实际上,lambda一般补货的变量是最终变量,即被final修饰的变量。
Lambda表达式例子
List<String> l = Arrays.asList(numbers);
List<Integer> r = l.stream()
.map(e -> new Integer(e))
.filter(e -> Primes.isPrime(e))
.distinct()
.collect(Collectors.toList());
stream函数将list流化,map将字符串映射为整数,filter过滤不是素数的数,distinct去重,collect接收一个Collector类型参数把结果收集到List中
未完待续