文章目录
Lambda管中窥豹(初识Lambda)
Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它
有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
在哪里以及如何使用Lambda
在函数式接口上使用Lambda表达式。
函数式接口就是只定义一个抽象方法的接口。
函数式接口举例:
public interface Comparator<T> {
int compare(T o1, T o2);
}
public interface Runnable{
void run();
}
public interface Predicate<T>{
boolean test (T t);
}
Lambda应用举例:
List<Apple> greenApples = filter(inventory, (Apple a) -> "green".equals(a.getColor()));
在上面的代码中,把 Lambda 表达式作为第二个参数传给 filter 方法,因为它这里需要
Predicate,而这是一个函数式接口。
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名。
凡是使用函数式接口的地方都可以使用Lambda表达式
例如:
() -> void,代表参数列表为空,返回void的函数。这正是Runnable所代表的。
(Apple, Apple) -> int,代表接收两个Apple作为参数且返回int的函数。
应用举例
通过一个例子,看看在实践中如何利用Lambda和行为参数化来让代码更为灵活,更为简洁。
原始方法如下:
缺点是只能读文件的第一行。如果你想要返回头两行,甚至是返回使用最频繁的词,怎么办?复制、粘贴,修改有用工作的那行代码?
第1步:行为参数化
你需要一种方法把行为传递给processFile
String result = processFile(“行为”);
第2步:使用函数式接口传递行为
// 定义函数式接口
@FunctionalInterface
public interface BufferedReaderProcessor {
String process(BufferedReader b) throws IOException;
}
// 把这个接口作为新的processFile方法的参数
public static String processFile(BufferedReaderProcessor p) throws IOException {
…
}
第3步:执行行为
public static String processFile(BufferedReaderProcessor p) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
return p.process(br); // 执行行为
}
}
第4步:传递Lambda
// 处理一行
String oneLine = processFile((BufferedReader br) -> br.readLine());
// 处理两行
String twoLines = processFile((BufferedReader br) -> br.readLine() + br.readLine());
Java8中常用的函数式接口
Java 8的库设计师帮你在java.util.function包中引入了几个新的函数式接口。
总结如下:
1. Predicate
java.util.function.Predicate<T>接口定义了一个名叫test的抽象方法,它接受泛型T对象,并返回一个boolean。
2. Consumer
java.util.function.Consumer<T>定义了一个名叫accept的抽象方法,它接受泛型T的对象,没有返回(void)。
@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));
3.Function
java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象