ToB企服应用市场:ToB评测及商务社交产业平台
标题:
【java8】stream学习笔记
[打印本页]
作者:
莱莱
时间:
2022-9-16 17:13
标题:
【java8】stream学习笔记
目录
一、什么是Stream
二、Stream的特点
串并行
干扰数据源
无状态
排序
三、创建Stream
四、中间操作
1. distinct
2. filter
3. map
4. mapToDouble
4. flatmap
5. limit
6. skip
7. peek
8. sorted
五、终点操作
1. Match
2. count
3. collect
4. find
5. forEach
6. max、min
7. reduce
8. toArray()
六、参考文档
一、什么是Stream
Stream是java8的新增特性,表示数据流。
二、Stream的特点
不存储数据:流是基于数据源的对象,本身不存储数据。
函数式编程:流的操作不会修改数据源。
延迟操作:流的很多操作如filter、map是延迟执行的,只有到了终点操作才会将操作顺序执行。
可以解绑:对于无线数量的流,有些操作(如limit(n)、findFirst())可以实现“短路操作”,访问到有限的元素后就可以返回。
纯消费:流只能被消费一次。如果使用完了一次流,仍然用这个流对象来操作时,会报异常。
串并行
所有的流操作都可以串行执行或者并行执行。除非显示的创建并行流,否则默认创建串行流。
串行:Collection.stream()、IntStream.range(int, int)
并行:Collection.parallelStream()、
通过parallel()方法可以将串行流转换为并行流,sequential()方法将流转换为串行流
干扰数据源
流可以从非线程安全的集合中创建。当流执行时,非并发的数据源不应该改变,否则会抛出java.util.ConcurrentModificationException异常。
无状态
大部分流的操作的参数都是函数式接口,可以使用Lambda表达式实现。它们用来描述用户的行为,称之为行为参数(behavioral parameters)。
如果这些行为参数有状态,则流的操作的结果可能是不确定的,比如下面的代码:
下面代码在并行执行时,由于执行顺序的不确定性,state.s的改变时机可能不同,导致多次执行时的结果不同
List<String> l = new ArrayList(Arrays.asList("one", "two", ……));
class State {
boolean s;
}
final State state = new State();
Stream<String> sl = l.stream().map(e -> {
if (state.s)
return "OK";
else {
state.s = true;
return e;
}
});
sl.forEach(System.out::println);
复制代码
排序
某些流的返回元素是有确定顺序的。这取决于它的数据源和中间操作。
比如List和Array创建的流是有序的,而HashSet创建的流是无序的。
sort()方法可以将流变得有序,而unordered()可以将流无序(不会打散元素)
当流有序时,如果用户并不关心顺序,可以使用unordered显示的去掉流的有序约束,可以改善某些情况下的并行性能
三、创建Stream
常见创建流的方法:
通过集合Collection的Stream()或parallelStream():如list.parallelStream()、Arrays.asList(1,2,3).stream()。
通过数组Arrays.stream(Object[])方法:如Arrays.stream(new int[]{1,2,3})。
流的静态方法:如:Stream.of(Object[])、IntStream.range(int, int)、Stream.iterate(Object, UnaryOperator)。
随机数流Random.ints()。
四、中间操作
中间操作是延迟执行的,不会修改原始数据流,在终点操作开始时才会开始执行
1. distinct
根据流中元素的hashCode()和equals()方法去除重复元素
List<Integer> list = Arrays.asList(1, 2, 3, 4, 4, 4, 5, 6);
list.stream().distinct().forEach(System.out::print); // 123456
System.out.println();
list.forEach(System.out::print); // 12344456
复制代码
2. filter
接收predicate,过滤数据
// 筛选出偶数
List<Integer> list = Arrays.asList(1, 2, 3, 4, 4, 4, 5, 6);
list.stream().filter(e -> e % 2 == 0).forEach(System.out::print); // 24446
复制代码
3. map
接收一个Function实例,重新印射数据
// 加1
List<Integer> list = Arrays.asList(1, 2, 3, 4, 4, 4, 5, 6);
list.stream().map(e -> e + 1).forEach(System.out::print); // 23455567
复制代码
4. mapToDouble
类似map,不过结果一定要是Double类型。
类似的方法还有mapToInt(),mapToLong()
// 加1.1
List<Integer> list = Arrays.asList(1, 2, 3, 4, 4, 4, 5, 6);
list.stream().mapToDouble(e -> e + 1.1).forEach(System.out::println);
/*
2.1
3.1
4.1
5.1
5.1
5.1
6.1
7.1
*/
// 加1
List<Integer> list = Arrays.asList(1, 2, 3, 4, 4, 4, 5, 6);
list.stream().mapToDouble(e -> e + 1).forEach(System.out::println);
/*
2.0
3.0
4.0
5.0
5.0
5.0
6.0
7.0
*/
复制代码
4. flatmap
[code] Stream flatMap(Function
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4