使用 Streams
一个 Stream 是在其上顺序和并行聚合操作可以执行元素的序列。任何给定的 Stream 都可能有无限量的数据流过它。结果,从 Stream 接收的数据在到达时被单独处理,而不是完全对数据进行批处理。当与 lambda 表达式结合使用时,它们提供了一种使用函数方法对数据序列执行操作的简明方法。
例如: ( 看到它在 Ideone 工作 )
Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange");
fruitStream.filter(s -> s.contains("a"))
           .map(String::toUpperCase)
           .sorted()
           .forEach(System.out::println);
输出:
苹果
香蕉
ORANGE
PEAR
上述代码执行的操作可归纳如下:
- 
使用静态工厂方法 Stream.of(values)创建一个包含有序Stream水果String元素的Stream<String>。
- 
所述 filter()操作只保留匹配给定的谓词(元件,当由所述谓词返回真测试),该元件。在这种情况下,它保留了包含a的元素。谓词以 lambda 表达式给出。
- 
所述 map()操作变换使用给定的函数,称为映射器的每个元素。在这种情况下,每个水果String使用方法参考String::toUppercase映射到其大写的String版本。请注意,如果映射函数返回与其输入参数不同的类型,则 map()操作将返回具有不同泛型类型的流。例如,在Stream<String>上调用.map(String::isEmpty)会返回一个Stream<Boolean>
- 
所述 sorted()操作根据其自然顺序排序Stream的元素(按字典顺序,在String的情况下)。
- 
最后, forEach(action)操作执行一个动作,该动作作用于Stream的每个元素,并将其传递给 Consumer 。在该示例中,每个元素都被简单地打印到控制台。该操作是终端操作,因此不可能再次对其进行操作。注意,由于终端操作,执行 Stream上定义的操作。如果没有终端操作,则不处理流。流不能重用。一旦调用终端操作,Stream对象就变得不可用。

操作(如上所示)被链接在一起以形成可以被视为对数据的查询。
关闭流
**请注意,通常不必关闭
Stream。**只需要关闭在 IO 通道上运行的流。大多数Stream类型不依赖于资源,因此不需要关闭。
Stream 界面扩展了 AutoCloseable 。可以通过调用 close 方法或使用 try-with-resource 语句来关闭流。
应该关闭 Stream 的示例用例是当你从文件创建线条时:
try (Stream<String> lines = Files.lines(Paths.get("somePath"))) {
    lines.forEach(System.out::println);
}
Stream 接口还声明了 Stream.onClose() 方法,该方法允许你注册 Runnable 处理程序,这些处理程序将在流关闭时调用。一个示例用例是生成流的代码需要知道何时使用它来执行某些清理。
public Stream<String>streamAndDelete(Path path) throws IOException {
    return Files.lines(path).onClose(() -> someClass.deletePath(path));
}
只有在 try-with-resources 语句显式或隐式调用 close() 方法时,才会执行运行处理程序。
处理订单
Stream 对象的处理可以是顺序的或并行的 。
在顺序模式中,元素按照 Stream 的来源顺序处理。如果订购了 Stream(例如 SortedMap 实现或 List ),则保证处理与源的顺序相匹配。但是,在其他情况下,应注意不要依赖于排序(参见: Java HashMap keySet() 迭代顺序是否一致? )。
例:
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 并且元素的数量减少为 1,则不会发生对诸如 sort 之类的方法的后续调用。这可以提高顺序 Stream 的性能 - 这是并行 Stream 无法实现的优化。
例:
// parallel
long howManyOddNumbersParallel = integerList.parallelStream()
                                            .filter(e -> (e % 2) == 1)
                                            .count();
System.out.println(howManyOddNumbersParallel); // Output: 2
与容器(或集合 )的差异
虽然可以在 Container 和 Streams 上执行某些操作,但它们最终用于不同的目的并支持不同的操作。容器更关注元素的存储方式以及如何有效地访问这些元素。另一方面,Stream 不能直接访问和操作其元素; 它更专注于作为集体实体的对象组,并作为整体对该实体执行操作。Stream 和 Collection 是针对这些不同目的的单独的高级抽象。