Java 8 Streams并尝试使用资源 [英] Java 8 Streams and try with resources

查看:197
本文介绍了Java 8 Streams并尝试使用资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为流API在这里使代码更容易阅读。
我发现一些相当烦人的东西。 Stream interface( java.util.stream.Stream )扩展了 AutoClosable interface( java.lang.AutoCloseable



所以如果你想正确关闭你的流必须使用资源试用。



清单1 。不太好,流未关闭。

  public void noTryWithResource(){
Set< Integer> photos = new HashSet< Integer>(Arrays.asList(1,2,3));

@SuppressWarnings(资源)列表< ImageView> collect = photos.stream()
.map(photo - > new ImageView(new Image(String.valueOf(photo))))。collect(Collectors。< ImageView> toList());
}

清单2 。有两个尝试:(

  public void tryWithResource(){
Set< Integer> photos = new HashSet< Integer& ;(Arrays.asList(1,2,3));

try(Stream< Integer> stream = photos.stream()){
try(Stream< ImageView> map = stream
.map(photo - > new ImageView(new Image(String.valueOf(photo))))){
列表< ImageView> collect = map.collect(Collectors。< ImageView> toList ));
}
}
}

清单3 。由于 map 返回一个流,所以 stream() map()函数必须关闭。

  public void tryWithResource2(){
Set< Integer> photos = new HashSet< Integer>(Arrays.asList(1,2,3));

try(Stream< Integer> stream = photos.stream();
流< ImageView> map = stream
.ma p(照片 - > new ImageView(new Image(String.valueOf(photo))))){
列表< ImageView> collect = map.collect(Collectors。< ImageView> toList());
}
}

我给的例子没有任何意义。为了示例,我将 Path 替换为具有 Integer 的jpg图像。但是不要让你分心这些细节。



这些可自动关闭的流是最好的方式。
我不得不说我不满意我显示的3个选项中的任何一个。
你觉得怎么样?还有其他更优雅的解决方案?

解决方案

您正在使用 @SuppressWarnings(resource) 可能会禁止对未关闭资源的警告。这不是 javac 发出的警告之一。网页搜索似乎表明,如果 AutoCloseable 未关闭,Eclipse会发出警告。



这是一个合理的警告,到 Java 7规范,介绍了 AutoCloseable


不再需要关闭的资源。 p>

但是, Java 8规范 for AutoCloseable 被放宽以删除必须关闭子句。现在,它部分地表示,


可以保存资源的对象,直到它关闭。



实际上,基类实现自动关闭是可能的,实际上是可行的,尽管不是所有的子类或实例都将保存可释放的资源。对于必须以完全一般性运行的代码,或者当知道AutoCloseable实例需要资源释放时,建议使用try-with-resources构造。然而,当使用诸如支持基于I / O和非I / O的表单的Stream这样的设施时,在使用非基于I / O的表单时通常不需要使用资源块。


Lambda专家组中广泛讨论了此问题; 此讯息总结了决定。除此之外,它还提到了 AutoCloseable 规范(如上所述)和 BaseStream 规范(由其他答案引用) 。它还提到可能需要调整Eclipse代码检查器的变更语义,大概不会无条件地为 AutoCloseable 对象发出警告。显然这个消息没有得到Eclipse的人,或者他们还没有改变。



总之,如果Eclipse的警告引导你认为你需要关闭所有 AutoCloseable 对象,这是不正确的。只有某些具体的 AutoCloseable 对象需要关闭。 Eclipse需要修复(如果还没有)不为所有 AutoCloseable 对象发出警告。


I thought that the stream API was here to make the code easier to read. I found something quite annoying. The Stream interface (java.util.stream.Stream) extends the AutoClosable interface (java.lang.AutoCloseable)

So if you want to correctly close your streams you have to use try with resources.

Listing 1. Not very nice, streams are not closed.

   public void noTryWithResource() {
    Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));

   @SuppressWarnings("resource") List<ImageView> collect = photos.stream()
            .map(photo -> new ImageView(new Image(String.valueOf(photo)))).collect(Collectors.<ImageView>toList());
}

Listing 2. With 2 imbricated try :(

   public void tryWithResource() {
    Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));

    try (Stream<Integer> stream = photos.stream()) {
        try (Stream<ImageView> map = stream
                .map(photo -> new ImageView(new Image(String.valueOf(photo))))) {
            List<ImageView> collect = map.collect(Collectors.<ImageView>toList());
        }
    }
}

Listing 3. As map returns a stream, both the stream() and the map() functions have to be closed.

    public void tryWithResource2() {
    Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));

    try (Stream<Integer> stream = photos.stream();
         Stream<ImageView> map = stream
                 .map(photo -> new ImageView(new Image(String.valueOf(photo))))) {
        List<ImageView> collect = map.collect(Collectors.<ImageView>toList());
    }
}

The example I give does not make any sense. I replaced Path to jpg images with Integer, for the sake of the example. But don't let you distract by these details.

What is the best way to go around with those auto closable streams. I have to say I'm not satisfied with any of the 3 options I showed. What do you think? Are there yet other more elegant solutions?

解决方案

You're using @SuppressWarnings("resource") which presumably suppresses a warning about an unclosed resource. This isn't one of the warnings emitted by javac. Web searches seem to indicate that Eclipse issues warnings if an AutoCloseable is left unclosed.

This is a reasonable warning according to the Java 7 specification that introduced AutoCloseable:

A resource that must be closed when it is no longer needed.

However, the Java 8 specification for AutoCloseable was relaxed to remove the "must be closed" clause. It now says, in part,

An object that may hold resources ... until it is closed.

It is possible, and in fact common, for a base class to implement AutoCloseable even though not all of its subclasses or instances will hold releasable resources. For code that must operate in complete generality, or when it is known that the AutoCloseable instance requires resource release, it is recommended to use try-with-resources constructions. However, when using facilities such as Stream that support both I/O-based and non-I/O-based forms, try-with-resources blocks are in general unnecessary when using non-I/O-based forms.

This issue was discussed extensively within the Lambda expert group; this message summarizes the decision. Among other things it mentions changes to the AutoCloseable specification (cited above) and the BaseStream specification (cited by other answers). It also mentions the possible need to adjust the Eclipse code inspector for the changed semantics, presumably not to emit warnings unconditionally for AutoCloseable objects. Apparently this message didn't get to the Eclipse folks or they haven't changed it yet.

In summary, if Eclipse warnings are leading you into thinking that you need to close all AutoCloseable objects, that's incorrect. Only certain specific AutoCloseable objects need to be closed. Eclipse needs to be fixed (if it hasn't already) not to emit warnings for all AutoCloseable objects.

这篇关于Java 8 Streams并尝试使用资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆