Stream 这一章感觉就很像 python 中的列表,或者更加具体的,python 中的 numpypandas


Streams follow the “what, not how” principle.

  • Stream 本身并不存放 Collection
  • Stream 不会改变 Collection 的内容,比如 filter 会产生出的 Stream
  • Stream 是 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 也是