(三)lamda
2019-08-22

lambda

lambda可以理解为匿名函数,由参数列表 箭头 函数主体组成语法

(parameters)->expression 或 (parameters)->{statements;}

第一种只有一句表达式,会默认返回表达式的值,所以隐藏了return。例如

(Integer x)-> x+x

第二种用于有多个表达式逻辑的代码块,必须使用return明确返回值。

(Integer x)-> { System.out.println("start ++x"); ++x; return x; };

函数接口

函数接口是仅有一个抽象方法的接口,例如Function接口

@FunctionalInterfacepublic interface Function<T, R> { R apply(T t);}

函数接口的作用是可以让lambda表达式为函数式接口的抽象方法提供实现,用lambda直接取代内部类比如runnable内部类接口

Runnable r2 = new Runnable(){ public void run(){ System.out.println("Hello World 1"); }};

Runnable 的lambda方式

Runnable r1 = () -> System.out.println("Hello World 1");

这两种方式完全等价,可以说离开函数接口,lambda表达式没有任何作用,一个lambda函数始终是函数接口的实现。

类型推断

lambda表达式可以在编辑期间自动推断参数类型例如

Function<Integer,Integer> fs = (x)-> x+x;

该例子可以通过Function接口的泛型化参数推断出x是Integer类型的参数。

初学者如何写好lambda表达式

熟悉相关函数接口,明确函数接口抽象方法的结构(参数列表和返回值类型)例如Function接口

@FunctionalInterfacepublic interface Function<T, R> { R apply(T t);}

观察抽象方法 R apply(T t);可见该抽象方法定义为由一个T类型的值返回一个R类型的返回值例如

Function<Integer,String> fs = (x)-> { String helloString = "hello" + x.intValue(); return helloString; };

声明为输入参数T为Integer类型,返回值R为String类型,所以lambda的参数列表数目(lambda参数可以自动推断)和函数接口抽象方法数目一致,lambda方法体返回结果类型和函数接口返回值类型一致即可。

方法引用

ClassName::staticMethod或者ClassName::instanceMethod静态方法的引用

public class Main { public static void main(String[] args) { List<String> strings = new ArrayList<>(); strings.forEach(Main::print); } public static void print(String abc){ System.out.println(abc); }}

需要注意的是所引用的方法需要和相关的函数接口匹配(和函数接口的参数类型和返回值一致),比如这个例子的forEach方法接受的函数接口是Consumer

default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }

Consumer是一个消费型的函数接口,接受一个T类型,无返回值

@FunctionalInterfacepublic interface Consumer<T> { void accept(T t);}

而我们的print方法接受一个String类型的参数,无返回值,且strings被限定为String类型,所以Consumer的T类型是String类型,因此print方法能和Consumer函数接口匹配。实例方法引用

List<String> list = new ArrayList<>(); list.stream().sorted(String::compareTo);

静态方法引用与实例方法引用的区别

静态方法ClassName::staticMethod ==== (x)->{statements}实例方法引用ClassName::staticMethod ==== (x,y)->{statements}instanceObject::instanceMethod ===== (x)->{statements}关注公众号,一起阅读IT经典书籍