【问题标题】:Close Java 8 Stream关闭 Java 8 流
【发布时间】:2016-12-06 11:52:16
【问题描述】:

如果我们使用像list.stream().filter(....).collect(..)..... 这样的Java 8 Stream 什么时候关闭这个流?

作为下一个例子,我们关闭流是好的做法吗?

Stream<String> stream = list.stream();
String result = stream.limit(10).collect(Collectors.joining(""));
stream.close();

【问题讨论】:

  • 来自文档:流具有 BaseStream.close() 方法并实现 AutoCloseable,但几乎所有流实例在使用后实际上不需要关闭。通常,只有源为 IO 通道的流(例如由 Files.lines(Path, Charset) 返回的流)才需要关闭。大多数流由集合、数组或生成函数支持,不需要特殊的资源管理。 (如果流确实需要关闭,可以在 try-with-resources 语句中将其声明为资源。)
  • 流一般不需要关闭。只有一些访问资源的流(例如DirectoryStream)需要关闭。最好的方法是使用try-with-resources 语句。
  • 1.由于它们很懒所以没有被初始化,2.它们实现了AutoCloseable,因此打开的流在空闲时会被关闭
  • 这是怎么重复的?这个问题询问流应该是否被关闭,另一个问题询问它们是否自动关闭 在某些特定情况下。如果你有可能因为金色徽章而单方面关闭问题,至少你应该先仔细阅读它们。
  • 我有一个类似的问题,似乎在阅读了其中一些回复之后,调用 close 方法是一种浪费,原因有很多。第一个是您必须在每个关闭方法中放置额外的 try-catch 块,这可能很耗时。第二个是任何 close 方法都可能只是终止资源,因此您可以通过使用 mystream = null; 获得相同的效果;陈述。第三是流不直接从文件本身读取,因此文件不会像其他语言一样被锁定打开,因此无需关闭它们。我就是这么理解的

标签: java java-8 java-stream


【解决方案1】:

通常根本不需要关闭流。您只需要关闭使用 IO 资源的流即可。

来自Stream documentation

流有一个BaseStream.close() 方法并实现AutoCloseable,但几乎所有的流实例在使用后实际上并不需要关闭。通常,只有源为 IO 通道的流(例如 Files.lines(Path, Charset) 返回的流)才需要关闭。大多数流由集合、数组或生成函数支持,不需要特殊的资源管理。 (如果流确实需要关闭,可以在 try-with-resources 语句中将其声明为资源。)

如果您需要关闭流,那么最佳做法是使用 try-with-resources 语句:

try ( Stream<String> stream = Files.lines(path, charset) ) {
    // do something
}

【讨论】:

    【解决方案2】:

    当然,默认情况下你应该关闭一个流。

    流是一个非常通用的 API;重点在于它代表了一个数据流不需要该数据的消费者了解数据的来源。

    关闭不需要关闭的流是免费的;未能关闭需要关闭的流可能会导致严重问题。您如何确定您正在编写的代码(当前使用不需要关闭的数据流)永远不会重新用于使用需要关闭的不同类型的流?

    我刚刚完成了大量代码的重构,这些代码过去使用内存数据库来使用 SQL 后端。有问题的代码大量使用了流,这是有充分理由的。将 JDBC 结果集封装在流中意味着我可以(……我想)很容易地实现我的目标。但是......我的新流封装了一个需要关闭的资源,而旧流没有。因为最初的开发者(在这种情况下是我,我在踢自己)没有关闭流,所以需要进行大量繁琐的调试。

    【讨论】:

      【解决方案3】:

      我必须补充一点,默认情况下流根本不会关闭!

      List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
      
      // "--" is not printed at all:
      list.stream().onClose(()->System.out.println("--")).forEach(x -> System.out.println(x));
      
      System.out.println("with try(){}:");
      
      // "--" is printed:
      try (Stream<Integer> stream = list.stream() ) {
          stream.onClose(() -> System.out.println("--")).forEach(x -> System.out.println(x));
      }
      

      【讨论】:

        【解决方案4】:

        您需要关闭的流之一是来自 org.hibernate.query.Query#getResultStream 的流

        您可以为此使用 try-with-resources:

        try (Stream<SomeEntity> resultStream = query.getResultStream()) {
            // process the stream
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多