迭代非列表的最短方式?

时间:2016-05-04 09:22:40

标签: java java-8

假设我有3个扫描程序实例,我想关闭它。

我能做到

sc.close()

为每个扫描仪。

或者我可以做类似

的事情
for (Scanner sc: new Scanner[]{sc1,sc2,sc3}) {
    sc.close();
}

使用Java 8有没有更短的方法?

类似于什么?

{sc1,sc2,sc3}.forEach((sc) -> sc.close());

3 个答案:

答案 0 :(得分:73)

从Java 7开始,您应该使用try-with-resources

try(Scanner sc1 = new Scanner(""); 
    Scanner sc2 = new Scanner(""); 
    Scanner sc3 = new Scanner("")){

}
//all scanners get closed implicitly

所以你根本不需要任何代码。

所有for-each或stream构造的问题是,理论上 - 如果第一个close()在调用基础源close()方法时出现异常,则以下扫描程序不会被关闭。 Scanner.close()实现捕获任何IOException,但不会发生其他异常。

try-with-resources构造处理的是,循环不是。

编辑:虽然您的问题针对更一般的方法,但上述解决方案是对您的特定问题的回应:处理AutoCloseable资源,无论如何都应该使用使用 try-with-resources 构造,根本不需要对close方法进行特殊处理(=对特定问题的最短解决方案)。

关于处理任意项目(没有资源)的更一般的问题,Java至少有两个选择:

从Array / Varargs创建一个列表并迭代它

for(YourItemType item : Arrays.asList(your,items,here)) {
  //do something
}

从Array / Varargs创建流并向其应用函数

Stream.of(your,items,here).forEach(item -> { doSomething});

当然" doSomething"可以用方法参考替换

Stream.of(your,items,here).forEach(this::myMethod);
...
void myMethod(YourItemType item){
  //doSomething
} 

该方法的问题是,必须在lambda表达式中显式处理已检查的异常。让我们看一下上面的例子,让myMethod抛出一个检查过的异常

void myMethod(YourItemType item) throws Exception

在这种情况下,您的stream语句必须看起来像

Stream.of(your,items,here).forEach(item -> {
  try {
    myMethod(item);
  } catch (Exception e){
    //omit or throw new RuntimeException(e);
  };

这看起来并不好看。但我们可以将lambda体放在一个单独的方法中

void myMethodQuietly(YourItemType item) {
  try {
    myMethod(item);
  }catch(Exception e){
    //omit or throw new RuntimeException(e);
  }
}

Stream.of(your,items,here).forEach(this::myMethodQuietly);

这种方法可能对您的特定资源问题感兴趣。我们可以将所有这些放入CompositeAutoCloseable中,该close()将在类外部创建的资源在调用public class CompositeAutoCloseable implements AutoCloseable { private List<Closeable> resources; public CompositeAutoCloseable(Closeable... resources) { this.resources = Arrays.asList(resources); //you could use a stream here too } @Override public void close() { this.resources.stream().forEach(this::closeQuietly); } void closeQuietly(Closeable res) { if(res == null) { return; } try { res.close(); }catch(Exception e){ //omit } } } 时安全地关闭所有资源

try(CompositeAutoCloseable cac = new CompositeAutoCloseable(sc1,sc2,sc3)) {
  //do something
}

一旦你有了这样的助手类,你可以再次使用try-with-resources。

{{1}}

我让你知道与初始解决方案相比这是否合理;)

答案 1 :(得分:3)

如果将实例化与处置分开,请使用Guava的com.google.common.io.Closer

答案 2 :(得分:-1)

尽管代码长度与其质量之间有时存在相关性,但这并不是用于选择代码的良好标准。

我可能会使用varargs并执行以下操作:

print()