Parallel processing 使用并行流高效地处理文件比较

Parallel processing 使用并行流高效地处理文件比较,parallel-processing,java-8,java-stream,Parallel Processing,Java 8,Java Stream,所以,我有多个txt文件,比如说txt1,txt2,…,每行有一些4到22个字符的文本,我有另一个具有类似值的txt文件,比如bigText。目标是检查bigTxt中出现在任何txt文件中的所有值,并输出这些值(我们保证,如果bigTxt的任何一行出现在任何txt文件中,则与该行的匹配只发生一次)。到目前为止,我拥有的最佳解决方案是有效的,但效率稍低。基本上,它看起来是这样的: txtFiles.parallelStream().forEach(file->{ List<Str

所以,我有多个txt文件,比如说
txt1,txt2,…
,每行有一些4到22个字符的文本,我有另一个具有类似值的txt文件,比如
bigText
。目标是检查
bigTxt
中出现在任何txt文件中的所有值,并输出这些值(我们保证,如果
bigTxt
的任何一行出现在任何txt文件中,则与该行的匹配只发生一次)。到目前为止,我拥有的最佳解决方案是有效的,但效率稍低。基本上,它看起来是这样的:

txtFiles.parallelStream().forEach(file->{
   List<String> txtList = listOfLines of this txtFile;
   streamOfLinesOfBigTxt.forEach(line->{
         if(txtList.contains(line)){
            System.out.println(line);
            //it'd be great if we could just stop this forEach loop here
            //but that seems hardish
         }
   });
});
txtFiles.parallelStream().forEach(文件->{
List txtList=此txtList文件的行列表;
streamOfLinesOfBigTxt.forEach(行->{
if(txtList.contains(行)){
系统输出打印项次(行);
//如果我们能在这里停止forEach循环就太好了
//但这似乎有些强硬
}
});
});
(注意:我在这里尝试使用Honza的“坏主意”解决方案突破forEach:但这肯定不是我想要的,因为它实际上使代码通常稍微慢一点或差不多)
这样做的一个小问题是,即使一个文件找到了
bigTxt
文件和其他txt文件之间的一行匹配,其他txt文件仍会尝试搜索该行的检查(即使我们已经找到了一个匹配项,这就足够了)。我试图阻止这种情况发生的事情是,首先迭代bigTxt行(不是并行的,但遍历每个txt文件是并行的),然后使用java的
anyMatch
,我得到了一个“流已经被修改或关闭”类型的错误,我后来理解这是因为
anyMatch
正在终止。因此,在对其中一个txt文件的一行调用
anyMatch
后,该流不再可用于我以后的处理。我想不出一种正确使用
findAny
的方法,我也不认为
allMatch
是我想要的,因为并非所有来自
bigTxt
的值都必须在其中一个txt文件中。对此的任何(并行)解决方案(甚至不严格包括来自Java8的东西)都是受欢迎的。谢谢。

如果
streamOfLinesOfBigTxt
是一个
,您将得到与问题中发布的代码相同的错误,因为您试图使用外部流的
forEach
多次处理该流。不清楚您为什么没有注意到这一点,但也许您总是在程序开始处理第二个文件之前停止程序?毕竟,对于大文件中的每一行,搜索
行列表所需的时间与这两个行数的乘积成线性关系

如果您想“检查任何txt文件中某个地方出现的所有bigTxt值并输出这些值”,您可以直接这样做:

Files.lines(Paths.get(bigFileLocation))
     .filter(line -> txtFiles.stream()
                 .flatMap(path -> {
                         try { return Files.lines(Paths.get(path)); }
                         catch (IOException ex) { throw new UncheckedIOException(ex); }
                     })
                 .anyMatch(Predicate.isEqual(line)) )
    .forEach(System.out::println);
这会造成短路,但仍存在处理时间随
n×m
而变化的问题。更糟糕的是,它将重新打开并重复读取TXT文件

如果要避免这种情况,在RAM中存储数据是不可避免的。如果存储它们,首先可以选择支持优于线性查找的存储:

Set<String> matchLines = txtFiles.stream()
    .flatMap(path -> {
        try { return Files.lines(Paths.get(path)); }
        catch (IOException ex) { throw new UncheckedIOException(ex); }
    })
    .collect(Collectors.toSet());

Files.lines(Paths.get(bigFileLocation))
     .filter(matchLines::contains)
     .forEach(System.out::println);
这取决于一个属性,即所有匹配行在所有这些文本文件中都是唯一的,正如您在问题中所述


我不认为并行处理会带来任何好处,因为I/O速度将主导执行。

欢迎使用堆栈溢出!看起来您的代码目前运行正常,您正在寻求改进。一般来说,这些问题对本网站来说过于固执己见,但你可能会在网站上找到更好的运气。记住要阅读,因为他们比这个网站严格一点。这个代码不是“稍微低效”,而是非常低效的,在一个大的
列表上反复调用
contains
Set<String> matchLines
    = Files.lines(Paths.get(bigFileLocation)).collect(Collectors.toSet());

txtFiles.stream()
        .flatMap(path -> {
            try { return Files.lines(Paths.get(path)); }
            catch (IOException ex) { throw new UncheckedIOException(ex); }
        })
        .filter(matchLines::contains)
        .forEach(System.out::println);