使用lines()流Lambda但需要关闭

时间:2017-03-08 07:47:25

标签: java javafx

我想在我的应用程序中做的是让用户使用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语句来包装它。

任何人都可以提出以优雅方式改进它的提示吗?

4 个答案:

答案 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.PathFiles类。
  • 使用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)

您可以完全删除BufferedReaderFileReader(无论如何都不应该使用)并使用以下代码(假设文件采用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的回答一样。