我有一个简单的要求,用户输入一堆单词,系统扫描超过 300 万个文本文件并找到包含这些关键字的文件。如果没有复杂的搜索/索引算法,最有效和最简单的方法是什么?
我想过为此使用Scanner
类,但不知道这么大文件的性能。性能不是很高的优先级,但它应该处于可接受的标准。
它应该在可接受的标准内
我们不知道可接受的标准是什么。如果我们谈论交互式用户,可能不会有一个简单的解决方案可以扫描 300 万个文件并在 5 秒内返回一些内容。
一个合理的解决方案是搜索索引,可能基于Lucence。
基于扫描仪/grep/find 等的解决方案的主要问题是它们很慢,无法扩展,并且必须一遍又一遍地完成昂贵的扫描工作(除非您存储中间结果......但这会不是简单的,基本上是一个索引器的人工昂贵的重新实现)。使用索引时,只有索引的创建和更新成本高,查询成本低。
如果没有复杂的搜索/索引算法,最有效和最简单的方法是什么?
复杂的搜索/索引算法。这里没有必要重新发明轮子。由于用户可以输入任何单词,因此您不能进行简单的预处理步骤,而是必须对文本中的所有单词进行索引。这就是 Lucene 为您所做的事情。
除了预处理和构建索引之外,没有其他快速搜索文本的方法。您可以为此推出自己的解决方案,也可以只使用 Lucene。
没有预处理的幼稚文本搜索将太慢而无法使用。
为什么不将系统调用包装到 grep?您可以通过 Runtime 类来实现。
在解析每个文本文件时,我会使用BufferedReader
并检查每一行文本是否匹配。
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
// Does this line containe the text?
if(line.contains(text)) {
System.out.println("Text found");
}
}
br.close();
我不确定这对于如此大量的文件是否会非常快。
What would be the most efficient and simple way to implement this without a complex searching / indexing algorithm
如果您不使用任何类型的索引算法,那么每次提交搜索时,您都需要读取每个文件。这样做的开销不在于“匹配”算法,而在于 I/O 延迟。所以,我不会太在意使用什么来匹配;Scanner
是直接的选择。
如果要提高性能,则需要使用某种预处理。您可以在大小允许的情况下将文件加载到内存中。您可以为每个文件(索引)创建一组单词。有太多算法可供您搜索,尤其是 Map/Reduce 上下文中的“字数统计”示例。Fork/Join
如果您想实现更高的并发性,您可能还想看看 Java 的框架。