java Stream的学习与简单练习
什么是stream
- Stream 流是java 1.8 的新特性之一。
- stream 是处理 :集合、数组、IO流等数据的抽象概念,简单来说就是处理数据。并返回一个新的流(不修改原有的数据,而是讲处理后的的数据放在另一个流中 – 惰性操作)。最后以终止操作结尾。
Stream 与 Collection 流和集合的区别
- 没有存储。流不是存储元素的数据结构;相反,它通过计算操作的管道传送来自数据结构、数组、生成器函数或 I/O 通道等源的元素。
- 对流的操作会产生结果,但不会修改其源
- 许多流操作,例如过滤、映射或重复删除,可以懒惰地实现
- 集合有大小的限制,而流没有
- 流中的元素在流的生命周期中只会被访问一次
获得流的方式
- 从一个Collection通过stream()和 parallelStream()方法
- 从一个数组通过Arrays.stream(Object[])
- 流类上的静态工厂方法 Stream.of(Object[]) 或 Stream.iterate(Object, UnaryOperator)
- 文件的lines() BufferedReader.lines();
- 可以从以下位置获得随机数流Random.ints();
- ……
流的操作和管道
- 流操作分为中间操作和 终端操作,结合起来形成流管道。一个流管道由一个源(例如一个 Collection、一个数组、一个生成器函数或一个 I/O 通道)组成;后跟零个或多个中间操作,例如 Stream.filter或Stream.map;和终端操作,例如Stream.forEach或Stream.reduce
- 中间操作返回一个新的流。执行中间操作,例如 filter()实际上并不执行任何过滤,而是创建一个新流,该流在遍历时包含与给定谓词匹配的初始流的元素。管道源的遍历直到管道的终端操作被执行后才开始。
- 有状态:指元素的处理不受之前元素的影响。如:filter and map(过滤和映射 惰性操作)
- 无状态:指操作只有拿到所有元素之后才能继续下去。如:distinct和sorted(去重和排序)
- 并行性:jdk默认串行,也可以在初始创建流时选在串行还是并行。如Collection有方法 Collection.stream()和Collection.parallelStream()
Stream 简单操作示例(一下示例以常用的集合为例)
/** 过滤空字符串 、计算空字符的个数
* stream().filter(过滤的条件) 过滤
* String -> !String.isempty 过滤不为空的字符
* collect(Collectors.toList()) 将过滤好的数据专入集合
* collect(Collectors.joining(",")) 用逗号拼字符集合数据并转为String类型
*/
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//过滤空字符串
List<String> filterStrings = strings.stream()
.filter(String -> !String.isEmpty())
.collect(Collectors.toList());
//空字符串的个数
long count = strings.stream().filter(String -> String.isEmpty()).count();
//用逗号拼接的字符串
String str = strings.stream()
.filter(s -> !s.isEmpty())
.collect(Collectors.joining(","));
System.out.println("用逗号拼接的字符串:"+str);
System.out.println("空字符串的个数 "+count);
System.out.println("不为空的字符串集合: "+filterStrings);
用逗号拼接的字符串:abc,bc,efg,abcd,jkl
空字符串的个数 2
不为空的字符串集合: [abc, bc, efg, abcd, jkl]
代码二
/**
* stream().map :映射集合中每个元素对用的结果
* i-> i+10 : i 代表集合中的每个元素 -> :映射处理转换数据i i+10 : 每个元素i 结果
* collect(Collectors.toList())将处理好的元素存入集合
* nums.forEach(System.out :: println); forEach 遍历nums 整形集合
*/
List<Integer> nums = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 遍历nums 集合
nums.forEach(System.out :: println);
//将集合中的每个元素都+10
List<Integer> mapNums = nums.stream()
.map(i -> i+10)
.collect(Collectors.toList());
System.out.println(mapNums);
//也可以先过滤在映射
List<Integer> numOne = nums.stream()
.filter(i -> i<=2 )
.map(i -> i*i)
.collect(Collectors.toList());
numOne.forEach(System.out::println);
3
2
2
3
7
3
5
[13, 12, 12, 13, 17, 13, 15]
4
4
代码三
/**
* mapToInt((s) -> Integer.valueOf(s)) 讲stringNums 中的string类型数据转为int
* summaryStatistics() 返回一个状态对象,用于收集计数、最小值、最大值、总和和平均值等统计信息。
*/
List<String> stringNums = Arrays.asList("3", "2", "2", "3", "7", "3", "5");
IntSummaryStatistics statistics = stringNums.stream().mapToInt((s) -> Integer.valueOf(s)).summaryStatistics();
System.out.println(statistics.getCount());;
System.out.println("max: "+statistics.getMax());
System.out.println("min: "+statistics.getMin());
System.out.println("sum: "+statistics.getSum());
System.out.println("Class: "+statistics.getClass());
System.out.println("avg: "+statistics.getAverage());
count: 7
max: 7
min: 2
sum: 25
Class: class java.util.IntSummaryStatistics
avg: 3.5714285714285716