我想在我的应用程序中做的是让用户使用filechooser选择一系列文本文件,然后如果它不包含指定的子索引,我的应用程序将过滤其中的一些文件。
使用lambda:
来表示我的代码 FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("choose files");
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("TXT files (*.txt)", "*.txt"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("CSV files (*.csv)", "*.csv"));
List<File> targetList = fileChooser.showOpenMultipleDialog(primaryStage);
if (targetList == null) {
System.out.println("targetList none");
}
targetList.parallelStream()
.filter(f->{
try {
return new BufferedReader(new FileReader(f)).lines()
.anyMatch(line-> (line.indexOf(",")!=-1));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
)
.collect(Collectors.toList());
它哼了一声,但并不完美!因为BufferedReader永远不会关闭,我需要用Buiky catch语句来包装它。
任何人都可以提出以优雅方式改进它的提示吗?
答案 0 :(得分:3)
这可以使用与this answer中相同的技术以优雅的方式解决。
可以创建应用函数的实用程序函数,然后使用try-with-resource-statement可靠地关闭资源。
使用它代码看起来像这样:
List<File> filteredList = targetList.parallelStream()
.filter(f -> f.exists())
.filter(f -> applyAndClose(
() -> new BufferedReader(new FileReader(f)),
reader -> reader.lines().anyMatch(line-> (line.indexOf(",") !=-1))))
.collect(Collectors.toList());
请注意,您必须保存collect
方法的结果,否则会丢失!另外,我在一个单独的步骤中测试文件是否存在。
效用函数本身如下所示:
/**
* Applies a function to a resource and closes it afterwards.
* @param sup Supplier of the resource that should be closed
* @param op operation that should be performed on the resource before it is closed
* @return The result of calling op.apply on the resource
*/
public static <A extends AutoCloseable, B> B applyAndClose(Callable<A> sup, Function<A, B> op) {
try (A res = sup.call()) {
return op.apply(res);
} catch (RuntimeException exc) {
throw exc;
} catch (Exception exc) {
throw new RuntimeException("Wrapped in applyAndClose", exc);
}
}
java.io.File
类和相关API大部分已过时。自Java 7以来使用文件的标准方法是java.nio.file.Path
和Files
类。String.contains
代替indexOf
。toList
使用静态导入:import static java.util.stream.Collectors.toList;
。使用这些代码看起来像这样:
List<Path> filteredList = targetList.stream()
.filter(f -> Files.exists(f))
.filter(f -> applyAndClose(
() -> Files.lines(f),
lines -> lines.anyMatch(line-> line.contains(","))))
.collect(toList());
答案 1 :(得分:1)
您可以使用try-with-resources Statement:
try-with-resources语句确保关闭每个资源 在声明的最后。
targetList.parallelStream()
.filter(f -> {
try (BufferedReader br = new BufferedReader(new FileReader(f))) {
return br.lines().anyMatch(line -> (line.indexOf(",") != -1));
} catch (IOException e) {
e.printStackTrace();
}
return false;
})
.collect(Collectors.toList());
答案 2 :(得分:1)
使用try with resources:
targetList.parallelStream()
.filter(f -> {
try (BufferedReader br = new BufferedReader(new FileReader(f))) {
return br.lines().anyMatch(line -> (line.contains(",")));
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
)
.collect(Collectors.toList());
答案 3 :(得分:1)
您可以完全删除BufferedReader
和FileReader
(无论如何都不应该使用)并使用以下代码(假设文件采用UTF-8
编码)。< / p>
targetList.parallelStream()
.filter(f -> {
try {
return Files.lines(f.toPath()).anyMatch(line -> line.contains(","));
} catch(IOException e) {
e.printStackTrace();
}
return false;
}).collect(Collectors.toList());
如果没有创建一个吞下异常的额外包装器,你就无法摆脱try / catch,就像Lii的回答一样。