Lambda表达式

一、Lambda表达式

可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它 有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。 Lambda表达式由参数、箭头和主体组成Lambda表达式语法示例

解析语法

1 、(String s) -> s.length() :该Lambda表达式具有一个String类型的参数并返回一个int。 Lambda没有return语句,因为已经隐含了return。
2、(User a) -> a.getWeight() > 150:改Lambda表达式有一个Apple类型的参数并返回一个boolean(人的体重是否超过150克)。
3、多行语句示例具有两个int类型的参数而没有返回值(void返回)。注意Lambda表达式可以包含多行语句,这里是两行。
4、() -> 12 :Lambda 表达式没有参数,返回一个int
5、Lambda表达式语法示例:Lambda表达式具有两个User类型的参数,返回一个int:比较两个User的体重。
以前的字符串排序:

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ClassC implements InterfaceA,InterfaceB{

	public static void main(String[] args) {
		List<String> names = Arrays.asList("A", "B", "C", "D");

		Collections.sort(names, new Comparator<String>() {
		    @Override
		    public int compare(String a, String b) {
		        return b.compareTo(a);
		    }
		});
		
	System.out.println(names.toString());
	}
}

Java 8 Lambda 更加简洁

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class ClassC implements InterfaceA,InterfaceB{

	public static void main(String[] args) {
		List<String> names = Arrays.asList("A", "B", "C", "D");

		Collections.sort(names, (a, b) -> b.compareTo(a));
		
	System.out.println(names.toString());
	}
}

Java 编译器可以自动推导出参数类型,不需要再多写类型。

二、函数式接口

1、引入

函数式接口就是只定义一个抽象方法的接口,Lambda表达式允许直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例 。也就是说,默认方法不算抽象方法,所以可以给函数式接口添加默认方法。

Runnabel r1 = () -> System.out.println("Hello world one"); 
# 注意:使用lambda表达式
 
Runnable r2 = new Runnable(){
    public viod run(){
        System.out.println("Hello world two"); 
    }
}      
# 注意:使用匿名类

public static void process(Runnable r){
      r.run();
}

process(r1);     #打印“Hello world one”
process(r2);     #打印“Hello world two”
process(() ->  System.out.println("Hello world three") );    #利用直接传递的lambda打印“Hello world three”

这个标注用于表示该接口会设计成一个函数式接口。如果你用@FunctionalInterface定义了一个接口,而它却不是函数式接口的话,编译器将返回一个提示原因的错误。
@FunctionalInterface不是必需的,但对于为此设计的接口而言,使用它是比较好的做法
注意:如果@FunctionalInterface如果没有指定,上面的代码也是对的。

@FunctionalInterface
public interface Coverter<F, T> {
	T convert(F from);
}


public class CoverterClass {

	public static void main(String[] args) {
		Coverter<String, Integer> converter = (from) -> Integer.valueOf(from);
		Integer converted = converter.convert("123");
		System.out.println(converted);    // 123
	}
}

2、常用的函数式接口

函数式接口 函数描述符 原始类型特化
Predicate T -> boolean IntPredicate
LongPredicate
DoublePredicate
Consumer T -> void IntConsumer
LongConsumer
DoubleConsumer
Function<T, R> T -> R IntFunction
IntToDoubleFunction
IntToLongFunction
LongFunction
LongToDoubleFunction
LongToIntFunction
DoubleFunction
ToIntFunction
ToDoubleFunction
ToLongFunction
Supplier () -> T BooleanSupplier
IntSupplier
LongSupplier
DoubleSupplier
UnaryOperator T -> T IntUnaryOperator
LongUnaryOperator
DoubleUnaryOperator
BinaryOperator (T, T) -> T IntBinaryOperator
LongBinaryOperator
DoubleBinaryOperator
BiPredicate<L, R> (L, R) -> boolean
BiConsumer<T, U> (T, U) -> void ObjIntConsumer
ObjLongConsumer
ObjDoubleConsumer
BiFunction<T, U, R> (T, U) -> R ToIntBiFunction<T, U>
ToLongBiFunction<T, U>
ToDoubleBiFunction<T, U>
自定义函数式接口
@FunctionalInterface
public interface MyFunction<T, R, U> {
	Boolean test(T t, R r, U u);
}

3、闭包

闭包就是一个函数的实例,且它可以无限制地访问那个函数的非本地变量。例如,闭包可以作为参数传递给另一个函数。它也可以访问和修改其作用域之外的变量。
Java 8的Lambda和匿名类可以做类似于闭包的事情,但有一个限制:它们不能修改定义Lambda的方法的局部变量的内容。这些变量必须是隐式final的。可以认为Lambda是对值封闭,而不是对变量封闭。这种限制存在的原因在于局部变量保存在栈上,并且隐式表示它们仅限于其所在线程。如果允许捕获可改变的局部变量,就会引发造成线程不安全的新的可能性。

4、闭方法引用

1)、Java 8的设计者决定允许方法作为值,让编程更轻松。此外,让方法作为值也构成了其他若干Java 8功能(如Stream)的基础。
2)、方法引用可以被看作仅仅调用特定方法的Lambda的一种快捷写法。它的基本思想是,如果一个Lambda代表的只是“直接调用这个方法”,那最好还是用名称来调用它,而不是去描述如何调用它。

Lambda 等效的方法引用
(Apple a ) -> a.getWeight Apple::getWeight
() ->Thread.currentThread().dumpStack() Thread.currentThread()::dumpStack
(str,i) ->str.substring(i) String::substring
String s -> System.out.println(s) System.out::println
3)、引用方法举例

将方法引用File::isHidden传递给listFiles方法

引用方法
四类方法引用

5、复合 Lambda 表达式

常用的复合表达式:Comparator、Predicate、Function三种复合表达式
1)、比较器复合
Comparator
2)、谓词复合
Predicate
3)、函数复合
函数复合(andThen和compose对比)

本文作者:[魂皓轩][1] 欢迎关注公众号

本人保留所有权益,转载请注明出处。
欢迎有故事、有想法的朋友和我分享,可发送至 e-mail: lwqforit@163.com

[1]: 1 "文章编辑专用,同步微信公众号,微信,博客园,知乎,微博,思否(segmentfault),掘金,QQ

posted @ 2019-12-06 21:38  魂皓轩  阅读(346)  评论(0编辑  收藏  举报