迭代非列表最短的方法?
假设我有3个扫描器实例,我想closures。
我可以
sc.close()
为每个扫描仪。
或者我可以做类似的事情
for (Scanner sc: new Scanner[]{sc1,sc2,sc3}) { sc.close(); }
用Java 8做这个有什么简单的方法吗?
类似的东西?
{sc1,sc2,sc3}.forEach((sc) -> sc.close());
从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()
方法时失败,则下面的扫描程序不会closures。 Scanner.close()
实现捕获任何IOException,但不会发生其他exception。
try-with-resources结构处理的是,循环没有。
编辑 :虽然你的问题针对一个更一般的方法,上面的解决scheme是对你的特定问题的回应:处理AutoCloseable
资源,这应该在任何情况下与try-with-resources结构一起使用,不需要特殊处理closures的方法在所有(=最短的解决scheme,您的特定问题)。
关于处理任意项目(没有资源)的更一般的问题,Java至less有两个选项:
从一个数组/可变参数创build一个列表并迭代它
for(YourItemType item : Arrays.asList(your,items,here)) { //do something }
从数组/可变参数创build一个stream,并将函数应用于它
Stream.of(your,items,here).forEach(item -> { doSomething});
当然,“doSomething”可以用方法引用来replace
Stream.of(your,items,here).forEach(this::myMethod); ... void myMethod(YourItemType item){ //doSomething }
这种方法的问题是,检查exception必须在lambdaexpression式中明确处理。 让我们拿上面的例子,让myMethod
抛出一个检查的exception
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 } } }
一旦你有这样一个辅助class,你可以再次尝试与资源使用它。
try(CompositeAutoCloseable cac = new CompositeAutoCloseable(sc1,sc2,sc3)) { //do something }
我把它留给你决定,与初始解决scheme相比这是否合理;)
如果实例化与处置分离,请使用Guava的com.google.common.io.Closer 。
虽然代码的长度与其质量之间有时是相关的,但这不是用来select代码的好的标准。
我可能会使用可变参数,并做这样的事情:
private void closeScanner(Scanner... scanners) { // Faff around with Java 8 in here if you like. for (Scanner s : scanners) { s.close(); } } // Some code. closeScanner(s, t, u);