1. 背景
lambda和stream是jdk1.8引入的新特性,他两通常配合一起使用。使用lambda表达式可以使代码变得更加紧凑整洁。stream更是能够简化对集合类的开发。
2. lambda概述
基本语法:
参数 ,箭头符号(->),表达式或语句块
(parameters)-> expression 或 (parameters)-> {statements; }
绝大多数情况下,编译器可以从上下文环境中推断出lambda表达式的参数类型。所以参数类型可以省略。当参数只有一个时,可省略小括号。当lambda表达式只有一条语句时,可以省略大括号、return语句和结尾的分号。
函数接口,是指只有一个抽象方法的接口(多个不行),可用作lambda表达式的返回值。接口的包路径是新增的java.util.function。这个包下面的所有接口(没有实现类)都有@FunctionalInterface注解。
比如:
Supplier<T> 拿到相应的结果
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
Consumer<T>处理对应的参数,无返回
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
lambda表达式主要用来定义行内执行的方法的类型接口,免去了使用匿名方法的麻烦。
lambda表达式可以将循环代码缩减到一行。
3. stream概述
在jdk1.8中新增了java.util.stream包,用来处理stream操作。stream是对集合的包装,可以看做是遍历数据集的高级迭代器。此外流还可以并行的处理,而不需要额外的编写多线程代码。
常用的方法有map,filter,limit,count,min,max,collect,foreach等。
map : 将一个对象映射到另一个对象,返回结果仍然是流
filter : 过滤操作,返回结果仍然是流
limit : 限制结果集个数,返回结果仍然是流
reduce : 规约操作,相同数据类型的数据进行操作,比如两个整数相加
count : 统计流中数据数量
min : 求最小值
max : 求最大值
collect : 汇总操作,汇总对应的处理结果
foreach : 遍历操作
stream的生成方式,主要是通过Stream的of方法,或者Collection接口实现类的stream方法 都可以获得流对象。
并行流的获取:Collection接口的实现类调用parallelStream方法就可以实现并行流,相应的就获得了并行计算的能力。也可以调用Stream接口的parallel方法也可以得到并行流。并行流的实现机制是通过fork/join进行处理的,先分解再合并。
4. 示例
遍历集合
String[] names = {"xl","zs","ls","ww"};
List<String> list = Arrays.asList(names);
// 1.8以前循环输出
for(String name : list){
System.out.println(name + ";");
}
// lambda表达式
list.forEach(name -> System.out.println(name + ";"));
// jdk1.8的另一个新特性,方法引用
list.forEach(System.out::println);
集合排序
String[] names = {"xl","zs","ls","ww"};
List<String> list = Arrays.asList(names);
// 1.8以前排序
Collections.sort(list, new Comparator<String>(){
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
// lambda排序
Collections.sort(list, (s1,s2) -> s1.compareTo(s2));
map/reduce
// 使用lambda表达式,每个值乘以2输出,并计算总和
List<Integer> nums = Arrays.asList(1,3,5,7);
// 1.8以前的实现
int sumNum = 0;
for(Integer num : nums){
System.out.println(num*2);
sumNum += num*2;
}
System.out.println(sumNum);
// map,reduce实现
nums.stream().map(num -> num*2).forEach(System.out::print);
int sumNum2 = nums.stream().map(num -> num*2).reduce((sum, num)->sum+num).get();
System.out.println(sumNum2);
获取数字的个数、最小值、最大值、总和以及平均值
//获取数字的个数、最小值、最大值、总和以及平均值
List<Integer> nums = Arrays.asList(1, 3, 5, 7, 11, 13);
IntSummaryStatistics stats = nums.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("max : " + stats.getMax());
System.out.println("min : " + stats.getMin());
System.out.println("sum : " + stats.getSum());
System.out.println("avg : " + stats.getAverage());
参考: