项目中用到的 JDK 7、JDK 8 的新特性(2)Lambda 表达式
此系列博文用于向我的同事介绍我在新项目中使用了一些 Java SE 1.7、Java SE 1.8 的新特性,以便同事阅读和维护这些代码。
2、Lambda表达式
从 JDK 8 开始,Java 中引入了一个 FunctionalInterface 的概念。FunctionalInterface 即只定义了一个(非 default)方法的接口,例如:
public interface Runnable {
void run();
}
public interface Callable<V> {
V call();
}
public interface Consumer<T> {
void accept(T t);
}
public interface BiConsumer<T, U> {
void accept(T t, U u);
}
等等。而 Lambda 表达式可以让我们用更少的代码来实现 FunctionalInterface 的匿名类。
例如:
Thread thread = new Thread(new Runnable() {
@Override public void run() {
doSomething();
}
}
可以用 Lambda 表达式写为:
Thread thread = new Thread(() -> {
doSomething();
});
如果代码块里只有一行代码,还可以省略掉大括号:
Thread thread = new Thread(() -> doSomething());
又例如:
Function<String, List<String>> function = new Function<>() {
@Override public List<String> accept(String str) {
list.add(str);
return list;
}
};
可以用 Lambda 表达式写为:
Function<String, List<String>> function = (str) -> {
list.add(str);
return list;
};
再例如:
Supplier<Set<String>> supplier = new Supplier<>() {
@Override public Set<String> get() {
return new HashSet<String>();
}
};
可以用 Lambda 表达式写为:
Supplier<Set<String>> supplier = () -> {
return new HashSet<String>();
};
由于代码块里只有一行代码,可以省略掉大括号和 return 关键字:
Supplier<Set<String>> supplier = () -> new HashSet<String>();
如果 Lambda 表达式对应的 FunctionalInterface 的方法没有参数,而且方法体内直接调用一个类的无参构造方法来返回一个对象的话,还可以使用 Class::new 这样的语法进一步简化代码:
Supplier<Set<String>> supplier = HashSet::new;
如果 Lambda 表达式的 Lambda 体也是通过调用一个对象的一个方法完成,而且调用方法的对象是 Lambda 表达式的参数列表中的第一个,而剩下的参数正好是给这个方法的实参,那么 Lambda 表达式可以简化为“类名::实例方法”的形式。这句话比较难理解,所以我们来看以下 3 个例子吧:
BiConsumer<List<String>, String> accumulator = (list, item) => list.add(item) ;
// List.add 方法作用于 Lambda 表达式的第一个参数 list
// List.add 方法的参数为 Lambda 表达式除了第一个参数以外的所有参数
// 以上 Lambda 表达式可简化为以下 Lambda 表达式
BiConsumer<List<String>, String> accumulator = List::add ;
BinaryOperator<List> combiner = (resultList, subList) => resultList.addAll(subList) ;
// List.addAll 方法作用于 Lambda 表达式的第一个参数 resultList
// List.addAll 方法的参数为 Lambda 表达式除了第一个参数以外的所有参数
// 以上 Lambda 表达式可简化为以下 Lambda 表达式
BinaryOperator<List> combiner = List::addAll ;
MyFunctionalInterface myFI = (str, beginIndex, endIndex) => str.substring(beginIndex, endIndex) ;
// String.substring 方法作用于 Lambda 表达式的第一个参数 str
// String.substring 方法的参数为 Lambda 表达式除了第一个参数以外的所有参数 beginIndex, endIndex
// 以上 Lambda 表达式可简化为以下 Lambda 表达式
MyFunctionalInterface myFI = String::substring