Stream 这一章感觉就很像 python 中的列表,或者更加具体的,python 中的 numpy
和 pandas
Streams follow the “what, not how” principle.
Stream
本身并不存放 CollectionStream
不会改变 Collection 的内容,比如filter
会产生出新的 StreamStream
是 lazy 的,在得到结果前不会运行
使用流的常见手法是:生成流 → 中间操作 → 获取结果
noninterference
Stream<String> words = wordList. stream (); words. forEach (s -> if (s.length () < 12) wordList. remove (s)); // ERROR--interference
不要在流的执行过程中,对原集合修改。实际上就算流没有在执行,也不要修改了
Stream 的生成
从 Collection
var l = new ArrayList<>(Arrays.asList(1, 2, 3));
var s = l.stream();
直接捏
// 1. 多个数据直接捏
var s = Stream.of(1, 2, 3);
// 2. 0 或 1 个数据直接捏
var s = Stream.ofNullable(null);
从 API
Java API 中,有很多方法会返回一个流,所以学好流很重要
try (var s = new Scanner(System.in).tokens()) {
s.forEach(System.out::println);
}
接受函数接口的特殊流
Intermediate Stream
filter
接收一个 Predicate
map & flatMap
正如其名,他会将原来的对象映射到另一种样子,也是接受一个 Function
因为也会有 Stream of Stream,此时可以通过 flatMap
来变成一个流
limit & skip
前者只要前 n 个,后者丢掉前 n 个
比如前面的 Scanner
的例子中,加上 limit
就可以实现中断
takeWhile & dropWhile
接收 Predicate
下次就不要再说了吧,应该心知肚明了。前者满足条件保留,后者满足条件丢弃
和 filter
还是不一样的,这俩会中断
concat
接收两个流合并
distinct
, sorted
Primitive Type Streams
原本是 Stream<Integer>
这么写的,使用包装类多少慢了,所以提供了⬆️
IntStream stream = IntStream.of(1, 1, 2, 3, 5);
stream = Arrays.stream(values, from, to); // values is an int[] array
IntStream zeroToNinetyNine = IntStream.range(0, 100); // Upper bound is excluded
IntStream zeroToHundred = IntStream.rangeClosed(0, 100); // Upper bound is included
IntStream lengths = words.mapToInt(String::length);
Stream<Integer> integers = IntStream.range(0, 100).boxed();
生成的方式多重多样,值得注意的是,box 和 unbox
toArray
会是对应 primitive 类型的 array- 专属的计数函数,类似
sum
Optional
会有对应新类summaryStatistics
也是