将许多文件与Java中的许多模式匹配

时间:2013-11-18 10:03:38

标签: java string algorithm pattern-matching bigdata

这就是我想要做的事情:一方面,我有一个带有〜100.000个字符串模式的文本文件(每个字符串都在一个新行中),其中大多数长约40-200个字符。另一方面,我有~130.000文件的大小,从几千字节到大文件,有几个数量惊人的兆字节(但是,95%的文件只有几个100kB)。

现在,我希望将130k文件中的每个与100k模式的所有进行匹配。

现在我正在使用.contains()方法进行匹配,这里有一些示例代码:

String file = readFile(somefile.pdf); // see benchmark below
String[] patterns = readFile(patterns.txt).split("\n"); // read 100k patterns into an array
for(int i = 0; patterns.length-1; i++){
    if(file.contains(patterns[i])){
        // pattern matched 
    }else{
        // patttern not matched
    }
}

我在一个相当强大的桌面系统(4核2.9ghz,4GB内存,SSD)上运行它,我的性能非常差:

当somefile.pdf是一个1.2mb的文件时,对所有100k模式的匹配需要大约43秒。 400kb是~14秒。一个50kb的文件是~2秒

这太慢了,我需要40x-50x倍的性能。我该怎么办?

5 个答案:

答案 0 :(得分:2)

在这些130k文件上创建搜索索引可能是最可持续的方法。

这里回答了类似的问题:Searching for matches in 3 million text files

通常在Java环境中使用的库/工具:

  • Lucene的
  • Solr的
  • elasticsearch

答案 1 :(得分:1)

如果您还没有,可以介绍一些快捷方式。

如果文件需要匹配所有模式,则只要模式与模式不匹配,就可以返回false。订购您的模式,将最有可能失败的模式放在最顶层 (如果另一方面文件需要与任何模式匹配,则可以在第一个模式匹配时立即返回true。在这种情况下,请将模式排序为最有可能的模式在顶部匹配。)

如果您希望所有文件与所有模式匹配,请确保先加载最小的文件。这样,您可以处理最容易比较的那些。你也可以尝试加载它们,这样你就可以处理最有可能首先失败的那些,但对我来说,对于模式而言,这对模式来说似乎更难。


另外,请确保只加载一次图案。

答案 2 :(得分:0)

如果你只是比较单词,一个可能的优化可能是预先索引130'000个文件。在最简单的情况下,这就像(伪代码):

for file in files
  read file as string
  split string into tokens (e.g. by white-space)
  set = all tokens in a HashSet
  for every pattern in patterns
      if set.contains(pattern)
          // pattern found
      else
          // pattern not found

当前解决方案的问题在于使用数组,从而导致数据库行话中的全表扫描(您真正设置的内容,或更Apache Lucene等更复杂的解决方案。

答案 3 :(得分:0)

您可能希望构建和检查巨型正则表达式的性能(即Pattern.compile("word1|word2|word3|..."),因为它构建的FSA应该比天真的方法具有更好的性能。

类似的问题:

What's the most efficient way to find one of several substrings in Python?

答案 4 :(得分:0)

你的for循环中有一个100,000倍的因子,你可以按顺序应用每个模式。

您需要找到一种方法将您的100K独立模式组合成一个模式,以便有效地处理。 “.contains”寻找特定的文本字符串;你也可以用正则表达式匹配来做到这一点。使用正则表达式匹配器,您可以将各个正则表达式模式组合成一个大型模式,预编译并应用该模式。 (请参阅Java正则表达式文档http://docs.oracle.com/javase/tutorial/essential/regex/

如果你关心的话,这会留下确定哪个模式被击中的问题。如果您检查像FLEX这样的lexing工具,它们会提供答案。你给它们相当于一组正则表达式,并且它们生成一个快速匹配器,它将告诉你哪些模式命中。