9.7 Lambda表达式
作为JDK 8推出的一个重要特性,Lambda 表达式受到了广泛的关注,它是自Java增添泛型和注释之后又一个大的变化。Lambda 对集合框架进行了增强,添加了两个对集合数据操作的包: java.util.function
和java.uti.Stream
.这里仅讲解Lambda表达式在集合框架中的基本应用方法。
Lambda表达式提供了一个参数列表和一个使用参数的主体,该主体可以是表达式或代码块。Lambda 格式如下:
(parameters) -> expression //主体为表达式
或
(parameters) ->{ statements; } // 主体为代码块
以下是Lambda表示式的简单例子:
(int x, int y) -> x + y //按收两个int类型的参数,并返回它们的和
(String s) -> System.out.print(s) // 接收一个string类型的对象s,并打印
下面看看Lambda表达式在集合中的几种应用情形。
1.对集合进行迭代
如果采用foreach语句迭代一个集合,代码片段如下:
String[] stars={"Jackie Chan", "Jim", "steve Joba", "Harry potter", "Taylor"};
List<String> movie= Arrays.asList (stars);
for (String m : movie) {
System.out.println (movie);
}
改用Lambda表达式来实现,代码如下:
String[] stars = {"Jackie Chan", "Jim", "steve Joba", "Harry potter", "Taylor"};
List<String> movie = Arrays.asList(stars);
movie.forEach(m -> System.out.println(m));//forEach()方法可以选代所有对象
或者使用双冒号操作符,简写代码如下:
movie.forEach (System.out::println);
可见,使用Lambda表达式能使代码更加紧凑、简沽。
2.对集合进行过滤
Lambda表达式和Stream结合使用会使操作简单易懂。Lambda可以支持许多操作,例如过滤操作,Stream提供的filter()
方法允许传递一个Lambda表达式作为参数并对其进行过滤,代码片段如下:
String[] stars-{ "Jackie Chan", "Jim","Steve Jobs", "Harry potter", "TaylorSwift"};
List<String> movie= Arrays.asList (stars);
//过滤掉List集合movie中长度为3及以下的元索:
List<String> filtered = movie.stream().filter(x -> x.length() > 3).collect(Collectors.toList());
System.out.printf("filtered list : %s", filtered);
这段代码创建的新集合filtered包含了所有长度大于3的元素,过滤掉了movie中的Jim。
3.对集合中的元素进行map和reduce操作
程序中经常会给集合中的每个元素赋予一定的操作, 如乘以或者除以某个数值,这类聚合操作(如平均值、总和、最小、最大和计数)可以由Lambda表达式传递给Stream的map()或reduce()
方法进行处理,达到并行操作集合的效果。map是对Stream对象的一种中间操作,通过指定的方法,它能够把Stream对象中的每一个 元素对应到一个新对象上。reduce是将多个值进行某种聚合操作后返回一个最终值
map( 示例代码如下:
List<Integer> numbers = Arrays.asList(8, 3, 3, 6, 5, 7, 6);
List<Integer> mult = numbers.stream().map(i -> i * 3).distinct().collect(Collectors.toList());
System.out.printf("new List : %s", mult);
此例中采用Stream类的distinct()
方法过滤集合中重复的数值,然后将每个数值乘以3,最后输出结果为: 24, 9, 18, 15, 21。
以上仅仅是Lambda表达式在集合中的几种基本用法,它还支持更多复杂的用法,如limit、sorted、count、min、max、 sum和collect
等操作。java.util.function
也包含了许多类和接口,如Predicate接口,它们也可以和Lambda表达式结合使用。此外,Lambda 表达式的另外一个重要用途是在图形用户界面Swing的事件响应中取代匿名的内部类,以及在比较器、多线程Runnable的实现中简化逻辑及代码。Lambda表达式的优势在于语法简洁,灵活,便于优化,以少量的代码实现相同的功能, 减少变量的定义及控制语句,从而减少代码bug,增强程序的稳定性。但缺点是代码不易理解,如果不熟练的话谨慎使用。