Stream是Java 8提供的新功能,是对集合(Collection)对象功能的增强,能对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数操作 (bulkdata operation)。 与Lambda 表达式结合,也可以提高编程效率、简洁性和程序可读性。
个人使用流的最大感受是在遍历List时,代码更加简洁高效。比如之前我向集合中添加元素是这样的:
以前的list循环遍历是:
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, 6);
for (Integer item : integerList){
System.out.println(item);
}
现在的list遍历是:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
list.stream().forEach(item -> System.out.println(item));
当然流还有许多特性,如果熟悉流,能让你的代码更优雅,更有效率。下面就让我们来一起感受一下Stream的魅力。
生成流的方式主要有五种
1、通过集合生成,应用中最常用的一种
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream<Integer> stream = integerList.stream();
2、通过数组生成
int[] intArr = {1, 2, 3, 4, 5, 6};
Stream<Integer> stream = (Stream) Arrays.stream(intArr);
3、通过值生成
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
Stream stream = Stream.empty(); //空流
4、通过文件生成
// 每一行都是流的一个元素
Stream<String> lines = Files.lines(Paths.get("data.txt"));
lines.forEach(line-> System.out.println(item));
5、通过函数生成
5.1 iterator
Stream<Integer> stream = Stream.iterate(0, n -> n + 1).limit(6);
iterate方法接受两个参数,第一个为初始化值,第二个为进行的函数操作,因为iterator生成的流为无限流,通过limit方法对流进行了截断,只生成5个偶数。
5.2 generator
Stream<Double> stream = Stream.generate(Math::random).limit(6);
generate方法接受一个参数,方法参数类型为Supplier ,由它为流提供值。generate生成的流也是无限流,因此通过limit对流进行了截断。
分为两种:中间操作和终端操作
例:通过filter筛选大于2小于5的数据
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream<Integer> stream = integerList.stream().filter(i -> i>2 && i<5);
所谓流映射就是将接受的元素映射成另外一个元素。
例:将Stream中每个字符串的长度映射成一个list
List<String> stringList = Arrays.asList("Hello word", "Lambdas is very useful", "In", "Action");
List<Integer> list = stringList.stream()
.map(item -> item.length())
.collect(Collectors.toList());
List<Integer> dataList = Arrays.asList(1, 2, 3, 4, 5, 6);
if (dataList.stream().allMatch(i -> i > 2)) {
System.out.println("所有元素都大于2");
} else {
System.out.println("不是所有元素都大于2");
}
List<Integer> dataList = Arrays.asList(1, 2, 3, 4, 5, 6);
if (dataList.stream().anyMatch(i -> i > 2)) {
System.out.println("至少有一个元素大于2");
} else {
System.out.println("所有元素都小于等于2");
}
List<Integer> dataList = Arrays.asList(1, 2, 3, 4, 5, 6);
long count = dataList.stream().count();
List<Integer> dataList = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = dataList.stream().filter(i -> i > 2).findFirst();
System.out.println(result.orElse(-1));
Java中非常讨厌的一点就是NPE空指针异常,需要逐行检查是哪个对象为空,带来大量的不必要精力损耗,而在每个方法中加入非空检查,阅读性和维护性都比较差。
Java 8中的Optional< T >是一个可以包含或不可以包含非空值的容器对象,在 Stream API中很多地方都使用到了Optional。
更多内容可以查看这篇博客:如何更好地使用Java 8的Optional
// 使用reduce函数
List<Integer> dataList = Arrays.asList(1, 2, 3, 4, 5);
int sum = dataList.stream()
.reduce(0, Integer::sum);
在这里插入代码片
获取最大最小值
// 使用reduce函数
List<Integer> dataList = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> max = dataList.stream()
.reduce(Integer::max);
System.out.println(max.orElse(-1));
// 使用max()函数
List<Integer> dataList = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> max = dataList.stream()
.max(Integer::compareTo);
System.out.println(max.orElse(-1));
List<Integer> stringList = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = stringList.stream()
.collect(toList());
Set<Integer> intSet = stringList.stream()
.collect(toSet());
利用Stream也可以拼接流元素,分组分区等,这里不过多介绍
joining 拼接流中的元素
groupingBy 分组
partitioningBy 分区