一、简介:
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
二、Lambda 表达式的语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
表达式三部分组成介绍:
1、paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断,另外当只有一个推断类型时可以省略掉圆括号。
2、->:可理解为“被用于”的意思
3、方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。
三、Lambda常用的方法示例:
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @author xqli
* @project:hisee
* @date 2018/11/9 19:04
* @description:
*/
public class LambdaTest {
private String id;
private String name;
private int age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public LambdaTest(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public static void main(String[] args) {
List<LambdaTest> list = new ArrayList<>();
list.add(new LambdaTest(String.valueOf(UUID.randomUUID()), "张三", 16));
list.add(new LambdaTest(String.valueOf(UUID.randomUUID()), "李四", 17));
list.add(new LambdaTest(String.valueOf(UUID.randomUUID()), "周六", 18));
list.add(new LambdaTest(String.valueOf(UUID.randomUUID()), "王五", 17));
list.add(new LambdaTest(String.valueOf(UUID.randomUUID()), "周六", 18));
/** 遍历(第一种语法)*/
list.forEach(next -> System.out.println(next.getName()));
/** 遍历(第二种语法)*/
list.forEach(next -> {
System.out.println(next.getName());
});
/**转hashSet */
Set<LambdaTest> set1 = list.stream().collect(Collectors.toSet());
/**转hashSet
* LambdaTest::getName 使用的方法引用(是Lambda类里的getName方法)
*/
Set<String> set2 = list.stream().map(LambdaTest::getName).collect(Collectors.toSet());
/**转treeSet (可去重) */
TreeSet<String> set3 = list.stream().map(LambdaTest::getName).collect(Collectors.toCollection(TreeSet::new));
/**转map*/
Map<String, String> map1 = list.stream().collect(Collectors.toMap(LambdaTest::getId, LambdaTest::getName));
/**转map*/
Map<String, String> map2 = list.stream().collect(Collectors.toMap(LambdaTest::getId, LambdaTest::getName, (k1, k2) -> k1));
/**分组*/
Map<String, List<LambdaTest>> map3 = list.stream().collect(Collectors.groupingBy(LambdaTest::getName));
/**分组count*/
Map<String, Long> map4 = list.stream().collect(Collectors.groupingBy(LambdaTest::getName, Collectors.counting()));
/**分组求和*/
Map<String, Integer> map5 = list.stream().collect(Collectors.groupingBy(LambdaTest::getName, Collectors.summingInt(LambdaTest::getAge)));
/**过滤条件(条件符合)*/
List<LambdaTest> temp1 = list.stream().filter(next -> 17 != next.getAge()).collect(Collectors.toList());
/**多个过滤条件(自定义过滤器)*/
Predicate<LambdaTest> customFilter = (next) -> (next.getAge() > 17);
Predicate<LambdaTest> clsFilter = (next) -> ("周六".equals(next.getName()));
List<LambdaTest> temp2 = list.stream().filter(customFilter).filter(clsFilter).collect(Collectors.toList());
/**取前多少个*/
List<LambdaTest> temp3 = list.stream().limit(2).collect(Collectors.toList());
/**升序排序*/
List<LambdaTest> temp4 = list.stream().sorted((next1, next2) -> (next1.getAge() - next2.getAge())).collect(Collectors.toList());
/**降序排序*/
List<LambdaTest> temp5 = list.stream().sorted((next1, next2) -> (next2.getAge() - next1.getAge())).collect(Collectors.toList());
/**求最大*/
LambdaTest lambdaTest = list.stream().max((next1, next2) -> (next1.getAge() - next2.getAge())).get();
/**求最小*/
LambdaTest lambdaTest2 = list.stream().min((next1, next2) -> (next1.getAge() - next2.getAge())).get();
/**求和*/
int sum = list.parallelStream().mapToInt(next -> next.getAge()).sum();
/**汇总数据*/
IntSummaryStatistics stats = list.stream().mapToInt((next) -> next.getAge()).summaryStatistics();
System.out.println("最大的数字 : " + stats.getMax());
System.out.println("最小的数字 : " + stats.getMin());
System.out.println("所有数字的总和 : " + stats.getSum());
System.out.println("所有数字的平均值: " + stats.getAverage());
}
}
正如你看到的,lambda表达式可以将我们的代码缩减到一行,也发现了lambda表达式的可以以数据流的方式处理集合,下面,我们看下通过Lambda表达式来代替函数式接口(Lambda表达式本质上是匿名方法,其底层还是通过invokedynamic指令来生成匿名类来实现),匿名类可以使用lambda表达式来代替,同样,在实现Runnable接口时也可以这样使用:
public class LambdaTest {
public static void main(String[] args) {
/**1.1普通写法*/
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello lambda");
}
}).start();
/**1.2 lambda写法*/
new Thread(() -> System.out.println("hello lambda")).start();
}
}
public class LambdaTest {
public static void main(String[] args) {
/**2.1普通写法*/
Runnable test = new Runnable() {
@Override
public void run() {
System.out.println("hello lambda");
}
};
/**2.2 lambda写法*/
Runnable sencondTest = () -> System.out.println("hello lambda");
test.run();
sencondTest.run();
}
}
备注:上述常用方法中多处用到了LambdaTest::getName,其方法引用(支持静态、实例、构造方法引用)是Lambda表达式的一个简化写法,所引用的方法其实是Lambda表达式的方法体的实现,其语法结构为:
ObjectRef::methodName