Lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。 我们先从最简单的示例来介绍Lambda表达式。
①用Lambda表达式实现Runnable:
@Test
public void test1(){
//使用Java8之前
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("使用Lambda表达式之前,需要这么写!");
}
}).start();
//使用Lambda表达式
new Thread(() -> System.out.println("使用Lambda表达式,只需要这一句话!")).start();
}
上面这个例子向我们展示了Lambda表达式的语法,你可以使用Lambda表达式写出如下代码:
(params) -> expression
(params) -> statement
(params) -> {statement}
如果你的方法不对参数进行修改、重写,只是在控制台打印点东西的话,那么可以这样写:
() -> System.out.println("使用Lambda表达式,只需要这一句话!")
如果你的方法接收两个参数,那么可以写成这样:
(int even, int odd) -> even + odd
顺便提一句,通常都会把Lambda表达式内部变量的名字起的短一些,这样可以使代码看的更加简洁。
②使用Lambda表达式进行事件处理:
@Test
public void test2(){
//使用Java8之前
JButton show = new JButton("展示");
show.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("使用Lambda表达式之前");
}
});
//使用Lambda表达式
show.addActionListener((e -> {
System.out.println("使用Lambda表达式");
}));
}
③使用Lambda表达式对列表进行迭代
@Test
public void test3(){
List features = Arrays.asList("hello","xidian","Lambda","google","youtube");
//使用Java8之前
for (Object feature : features){
System.out.println(feature);
}
//使用Lambda表达式
features.forEach(n -> System.out.println(n));
//使用Java8的方法引用更方便,方法引用由:双冒号操作符标识
features.forEach(System.out :: println);
}
列表循环的最后一个例子展示了如何在Java8中使用方法引用,代码更加简洁。
④使用Lambda表达式和函数式接口Predicate:
@Test
public void test4(){
List languages = Arrays.asList("Java","Scala","C++","Haskell","Lisp");
System.out.print("J开头的语言有:");
filter(languages,(str) -> str.startsWith("J"));
System.out.print("a结束的语言有:");
filter(languages,(str) -> str.endsWith("a"));
System.out.print("所有语言:");
filter(languages,(str) -> true);
System.out.print("名字长度大于4的语言:");
filter(languages,(str) -> str.length() > 4);
}
public void filter(List names ,Predicate predicate){
for (String name : names){
if (predicate.test(name)){
System.out.println(name + " ");
}
}
}
⑤使用Lambda表达式演示Map和Reduce
@Test
public void test5(){
List costBeforeTax = Arrays.asList(100,200,300,400,500);
//不使用Lambda表达式为每个订单加上12%的税
for (int cost : costBeforeTax){
double v = cost + .12 * cost;
System.out.println(v);
}
//使用Lambda表达式
costBeforeTax.stream().map((cost) -> cost + .12 * cost).forEach(System.out :: println);
//计算加税之后的总金额
Double total = costBeforeTax.stream().map((c) -> c + c * .12).reduce((sum, c) -> sum += c).get();
System.out.println("计算加税之后的总金额: " + total);
}
在上面的例子中,可以看到map将集合类元素进行转换,reduce函数可以将所有值合并成一个。map和reduce操作是函数式编程的核心操作。
⑥对列表的每个元素应用函数
我们通常需要对列表的每个元素使用某个函数,例如逐一乘以某个数,初一某个数等,这些操作都很适合用map()方法,可以将转换逻辑以Lambda表达式的形式放在map函数里,就可以对集合中的各个元素进行转换了:
@Test
public void test6(){
List G7 = Arrays.asList("USA","Japan","France","Germany","Italy","U.K.","Cananda");
//将元素中的小写字母转化为大写字母
String collect = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(","));
System.out.println(collect);
}
⑦计算集合元素的最大值、最小值、总和及平均值
IntStream LongStream DoubleStream 等流的类中,有一个非常有用的方法叫做summaryStatistics()。可以返回IntSummaryStatistics,LongSummaryStatistics, DoubleSummaryStatistics,描述流中元素的各种摘要数据。
@Test
public void test7() {
List primes = Arrays.asList(2,3,5,7,11,23,12,32,2,544);
IntSummaryStatistics ststs = primes.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("最大元素是:" + ststs.getMax());
System.out.println("最小元素是:" + ststs.getMin());
System.out.println("元素总和是:" + ststs.getSum());
System.out.println("元素平均值是:" + ststs.getAverage());
System.out.println("元素个数是:" + ststs.getCount());
}