迭代非列表的最短方法?
假设我有 3 个要关闭的扫描程序实例。
我可以做
sc.close()
对于每个扫描仪。
或者我可以做这样的事情
for (Scanner sc: new Scanner[]{sc1,sc2,sc3}) {
sc.close();
}
有没有更短的方法来做到这一点与Java 8?
类似的东西?
{sc1,sc2,sc3}.forEach((sc) -> sc.close());
假设我有 3 个要关闭的扫描程序实例。
我可以做
sc.close()
对于每个扫描仪。
或者我可以做这样的事情
for (Scanner sc: new Scanner[]{sc1,sc2,sc3}) {
sc.close();
}
有没有更短的方法来做到这一点与Java 8?
类似的东西?
{sc1,sc2,sc3}.forEach((sc) -> sc.close());
从Java 7开始,您应该使用试用资源
try(Scanner sc1 = new Scanner("");
Scanner sc2 = new Scanner("");
Scanner sc3 = new Scanner("")){
}
//all scanners get closed implicitly
因此,您根本不需要任何代码。
所有 for-each 或流构造的问题在于,从理论上讲,如果第一个在调用基础源的方法时失败并出现异常,则以下扫描程序不会关闭。该实现捕获任何 IOException,但没有可能发生的其他异常。close()
close()
Scanner.close()
使用资源进行试验的构造处理这一点,循环不处理。
编辑:虽然您的问题针对的是更通用的方法,但上述解决方案是对您的特定问题的回应:处理资源,在任何情况下都应与资源试验构造一起使用,根本不需要对关闭方法进行特殊处理(=您的特定问题的最短解决方案)。AutoCloseable
关于处理任意项目(没有资源)的更一般的问题,Java至少有两个选项:
从数组/Varargs 创建列表并对其进行迭代
for(YourItemType item : Arrays.asList(your,items,here)) {
//do something
}
从数组/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.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
}
我由您来决定与初始解决方案相比,这是否有意义;)