首页 > 代码库 > 《Java 8 实战》(二)—— Lamda
《Java 8 实战》(二)—— Lamda
Lamda表达式可以理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表/函数主体/返回类型,可能还有一个可以抛出的异常列表。
Lamda表达式由参数/箭头和主体组成:
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
之前的代码形式:
Comparator<Apple> byWeight = new Comparator<Apple>() {
public int compare(Apple a1, Apple a2) {
return a1.getWeight().compareTo(a2.getWeight());
}
}
Java 8 中有效的Lamda表达式:
1, (String s) -> s.length()
具有一个String类型的参数,并返回一个int。Lamda表达式没有return语句,因为已经隐含了return。
2, (Apple a) -> a.getWeight() > 150
参数为Apple类型,返回一个boolean类型。
3, (int x, int y) -> {
System.out.println("Result");
System.out.println(x+y);
}
该Lamda表达式具有两个int类型的参数而没有返回值。Lamda表达式可以包含多行语句。
() -> {return "Mario";}
该Lamda表达式也是有效的。
4, () - > 42
该Lamda表达式没有参数,返回一个int
5, (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())
该表达式具有两个Apple类型的参数,返回一个int
无效Lamda表达式:
(Integer i) -> return "Alan" + i;
(String s) -> {"IronMan";}
第一个表达式中,return是一个控制流语句。要使得这个语句有效,需要加上花括号。
第二个表达式中,"IronMan" 是一个表达式,不是语句。要使得此Lamda有效,可以去除花括号和分号。
Lamda基本语法:
(parameters) -> expression
or
(parameters) -> { statements;}
可以使用Lamda表达式的地方 —— 函数式接口
函数式接口就是只定义一个抽象方法的接口。如Comparator和Runnable接口。
Lamda表达式可以直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例。
函数式接口的抽象方法的签名就是Lamda表达式的签名。这种抽象方法叫做函数描述符。
新的Java API中,函数式接口带有@FunctionalInterface的标注。如果用@FunctionalInterface定义了一个接口,但它却不是函数式接口的话,便一起将返回一个提示原因的错误,例如“Multiple non-overriding abstract methods found in interface Foo”,表明存在多个抽象方法。
使用Lamda表达式的步骤:
1,行为参数化:
提取Lamda表达式,设计好参数,函数主体和返回值。
2,使用函数式接口来传递行为:
创建一个能匹配Lamda表达式的函数式接口I,并把这个接口作为参数传递给需要使用Lamda表达式的函数M。
3,执行函数式接口中的行为
在函数M中调用接口I中的抽象函数
4,传递Lamda表达式
常用函数式接口:
Java 8 以前已有的函数式接口:
Comparable
Runnable
Callable
Java 8 在java.util.function包中引入的新的函数式接口:
Predicate
@FunctionalInterface public interface Predicate<T>{ boolean test(T t); } public static <T> List<T> filter(List<T> list, Predicate<T> p) { List<T> results = new ArrayList<>(); for(T s: list){ if(p.test(s)){ results.add(s); } } return results; } Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty(); List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);
Consumer
@FunctionalInterface public interface Consumer<T>{ void accept(T t); } public static <T> void forEach(List<T> list, Consumer<T> c){ for(T i: list){ c.accept(i); } } forEach(Arrays.asList(1,2,3,4,5),(Integer i) -> System.out.println(i));
Function
@FunctionalInterface public interface Function<T, R>{ R apply(T t); } public static <T, R> List<R> map(List<T> list,Function<T, R> f) { List<R> result = new ArrayList<>(); for(T s: list){ result.add(f.apply(s)); } return result; } List<Integer> l = map(Arrays.asList("lambdas","in","action"),(String s) -> s.length());
Lamda及函数式接口例子
使用案例 | Lambda的例子 | 对应的函数式接口 |
布尔表达式 | (List<String> list) -> list.isEmpty() | Predicate<List<String>> |
创建对象 | () -> new Apple(10) | Supplier<Apple> |
消费一个对象 | (Apple a) -> System.out.println(a.getWeight()) |
|
Lambda的例子 对应的函数式接口
消费一个对象 (Apple a) ->
System.out.println(a.getWeight())
Consumer<Apple>
从一个对象中
选择/提取
(String s) -> s.length() Function<String, Integer>或
ToIntFunction<String>
合并两个值 (int a, int b) -> a * b IntBinaryOperator
比较两个对象 (Apple a1, Apple a2) ->
a1.getWeight().compareTo(a2.getWeight())
Comparator<Apple>或
BiFunction<Apple, Apple, Integer>
或ToIntBiFunction<Apple, Apple>
《Java 8 实战》(二)—— Lamda