因为经常逛
, 最近也在看 reactive 和 storm 以及前一阵子也用流式 ORM 框架
- stackoverflow
与
- speedment
整合改造了 中的单点登录, 深深的感受到 java8 已经融入我们很深了,尤其是 Spring5 对其进行大力支持,觉得有必要再对自己的知识整理一下,顺带就把
- Springboot
一些东西自己拿过来整理翻译一下,里面也会加入一些自己的理解 版本只关注于 Java SE 8
- stackoverflow
流表示一系列元素并支持不同类型的操作来对这些元素执行计算。在 Java 8 中,Collection 接口有两种方法来生成 Stream
A 是可以执行顺序和并行聚合操作的一系列元素 。 任何给定的 "Stream" 都可能有无限量的数据流过它。 你所得到的结果是从 "Stream" 接收的数据在到达时被单独处理,而不是完全对数据执行批处理。 当与 结合时,它们提供了使用函数方法对数据序列执行操作的简明方法。
Example:( )
- Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange");
- fruitStream.filter(s -> s.contains("a"))
- .map(String::toUpperCase)
- .sorted()
- .forEach(System.out::println);
APPLE
BANANA
ORANGE
PEAR
上述代码执行的操作可以总结如下:
的顺序排序 的 元素
- String
使用 映射到将 string 字符串转换为大写版本 。 Note 如果映射函数返回与其输入参数不同的类型,那么
- String
操作将返回具有不同泛型类型的流。 例如在一个
- map()
调用
- Stream
返回一个
- .map(String :: isEmpty)
- Stream<Boolean>
的元素进行排序 根据它们的自然排序(根据在'String'的情况下对所在字典的顺序,其实都知道)。
- Stream
5. 最后, 操作执行一个动作,作用于 "Stream" 的每个元素,将其传递给一个 。 在该示例中,每个元素只是被打印到控制台。 该操作是终端操作,因此不可能再次进行操作。
6.
Note 在
中定义的操作之所以被执行,是因为最后有终端操作。 假如没有终端操作,'Stream'将不被处理,因为'Stream'输出不被任何终端操作使用 (省的浪费计算资源,所以很多书上称之为被动式 foreach)。
- Stream
[
操作(如上所示)链接在一起以形成可以被视为对数据的查询
一个
不能重复使用。 一旦调用任何中间或终端操作,"Stream" 对象将变得不可用。
- Stream
代替地使用中间
- Stream
对象以便将中间操作链接在一起通过一系列
- Stream
操作来生成一个
- Stream
对象作为中间对象,最后再调用这个生成的
- Stream
对象来完成最终的操作,最后一步的操作只能进行一次,之后,此流已经没了 (生命周期已结束)。
- Stream
- Stream<String> stream =
- Stream.of("d2", "a2", "b1", "b3", "c")
- .filter(s -> s.startsWith("a"));
- stream.anyMatch(s -> true); // The Stream has been used and is now consumed.
- stream.noneMatch(s -> true); // IllegalStateException; stream was already used
接口扩展了 。Streams 可以通过调用 方法或使用 try-with -resource 语句来关闭。
- Stream
请注意,Stream 通常不必关闭。仅需要关闭在 IO 通道上运行的流。 大多数
型不对资源操作,因此不需要关闭。
- Stream
应该关闭的示例用例是,当您从文件创建一个
- Stream
行时:
- Stream
- try(final Stream<String> lines = Files.lines(Paths.get("somePath"))){
- lines.forEach(System.out::println);
- }
接口也声明了 方法,它允许你注册 处理程序,当 流关闭。 一个示例用例是产生流的代码需要知道它何时被消耗以执行一些清理。
- Stream
- public Stream<String>streamAndDelete(Path path) throws IOException {
- return Files.lines(path)
- .onClose(()->someClass.deletePath(path));
- }
运行处理程序只有在调用
方法时才会执行,例如通过 try-with-resources:
- close()
- Path myPath = Paths.get("somePath");
- try(final Stream<String> lines = streamAndDelete(myPath)){
- lines.forEach(System.out::println);
- }
- Files.exists(myPath); // returns false
If close() isn't called, explicitly or implicitly, then the handler will not be called either:
如果没有明确或隐式地调用
,那么处理程序不会被调用:
- close()
- streamAndDelete(myPath)
- .forEach(System.out::println);
- Files.exists(myPath); // returns true
对象的处理可以是顺序或 。
- Stream
在 sequential 模式中,按照 "Stream" 的源的顺序处理元素。 如果
是有序的(例如 实现或 ,处理过程保证匹配源的排序。 然而,在其他情况下,应注意不要依赖于顺序(参见: )。
- Stream
- List<Integer> integerList = Arrays.asList(0, 1, 2, 3, 42);
- // sequential
- long howManyOddNumbers = integerList.stream()
- .filter(e -> (e % 2) == 1).count();
- System.out.println(howManyOddNumbers); // Output: 2
并行模式允许在多个核上使用多个线程,但不能保证处理元素的顺序。
如果在顺序的
上虽然调用了多个方法,则不一定必须要调用每个方法。 例如,如果一个
- Stream
被过滤,并且元素的数量减少到一,则不会发生对诸如
- Stream
的方法的后续调用。 这可以提高顺序的
- sort
的性能 - 这是一个并行的
- Stream
不可能实现的优化。
- Stream
- // parallel
- long howManyOddNumbersParallel = integerList.parallelStream()
- .filter(e -> (e % 2) == 1).count();
- System.out.println(howManyOddNumbersParallel); // Output: 2
来源: