Java使用流

示例

AStream是可以在其上执行顺序和并行聚合操作的元素序列。任何给Stream定都可能有无限量的数据流通过它。结果,从a接收到的数据在到达时将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);

输出:

苹果
香蕉

上面的代码执行的操作可以总结如下:

  1. 使用静态工厂方法创建一个Stream<String>按顺序排列Stream的水果String元素顺序。Stream.of(values)

  2. 该filter()操作仅保留与给定谓词匹配的元素(在由谓词测试时返回true的元素)。在这种情况下,它将保留包含的元素"a"。谓词以lambda表达式形式给出。

  3. 该map()操作使用称为映射器的给定函数转换每个元素。在这种情况下,每个水果String都String使用method-reference映射到其大写版本String::toUppercase。

    请注意,map()如果映射函数返回与其输入参数不同的类型,则该操作将返回具有不同通用类型的流。例如,在Stream<String>调用时.map(String::isEmpty)返回一个Stream<Boolean>

  4. 该sorted()操作会Stream根据其元素的自然顺序对它们进行排序(按字典顺序String)。

  5. 最终,该forEach(action)操作执行一个对的每个元素起作用的动作Stream,并将其传递给使用者。在该示例中,每个元素仅被打印到控制台。此操作是终端操作,因此无法再次对其进行操作。

    注意由于终端操作Stream而执行在上定义的操作。如果没有终端操作,则不会处理该流。流不能重复使用。一旦调用了终端操作,该对象将变得不可用。Stream

操作(如上所述)被链接在一起以形成可视为对数据的查询。


关闭流

注意,Stream通常不必关闭。仅需要关闭在IO通道上运行的流。大多数Stream类型不对资源进行操作,因此不需要关闭。

该Stream接口扩展AutoCloseable。可以通过调用close方法或使用try-with-resource语句来关闭流。

一个Stream应关闭a的示例用例是Stream从文件创建a行时:

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));
}

仅当close()try-with-resources语句显式或隐式调用该方法时,运行处理程序才会执行。


处理订单

甲Stream对象的处理可以是顺序的或平行的。

顺序模式下,将按的来源顺序处理元素Stream。如果对Stream排序(例如SortedMap实现或List),则保证处理与源的排序匹配。但是,在其他情况下,应注意不要依赖于顺序(请参阅:JavaHashMap keySet()迭代顺序是否一致?)。

示例

List<Integer> integerList = Arrays.asList(0, 1, 2, 3, 42); 

// 顺序的 
long howManyOddNumbers = integerList.stream()
                                    .filter(e -> (e % 2) == 1)
                                    .count(); 

System.out.println(howManyOddNumbers); // 输出2

住在伊迪欧

并行模式允许在多个内核上使用多个线程,但是不能保证处理元素的顺序。

如果在顺序上调用多个方法Stream,则不必调用每个方法。例如,如果将aStream过滤并将元素数减少为1,sort则不会发生对方法的后续调用。这可以提高顺序性能Stream-并行无法实现的优化Stream。

示例

// 平行
long howManyOddNumbersParallel = integerList.parallelStream()
                                            .filter(e -> (e % 2) == 1)
                                            .count();

System.out.println(howManyOddNumbersParallel); // 输出2

住在伊迪欧


与容器(或集合)的区别

尽管可以在容器和流上执行某些操作,但它们最终有不同的用途并支持不同的操作。容器更加关注元素的存储方式以及如何高效地访问这些元素。Stream另一方面,A不提供对其元素的直接访问和操纵。它更专注于作为一个集合实体的对象组,并在整体上对该实体执行操作。Stream并且Collection是针对这些不同目的的单独的高级抽象。