我有一个文本文件,其中包含大约30,000个单词,每个单独的行按字母顺序排列。
我还有Set<String> set
包含~10个单词。
我想检查set
中的任何字词是否在单词列表(文本文件)中。
到目前为止,我的方法是:
set
是否包含该字词这看起来很糟糕。例如,如果我正在检查我的集合中以字母 b 开头的单词,我认为检查文本文件中的单词没有任何意义,请使用 a&amp; c,d,.. 等。
我建议的解决方案是将文本文件分成26个文件,一个文件用于以字母表中每个字母开头的单词。 有比这更有效的解决方案吗?
注意:我知道30,000个单词不是 大单词列表但我必须在移动设备上多次执行此操作,因此性能是关键。
答案 0 :(得分:2)
您可以进一步将Hash Sets用于整个wordlist文件。字符串比较是昂贵的,因此最好创建一个整数的HashSet。您应该阅读单词列表(假设单词不会从30,000增加到300万单位),并将所有单词保存在整数哈希集中。添加到Integer Hashset时使用:
wordListHashSet.add(mycurrentword.hashcode());
你已经提到你有一个10字的字符串哈希,如果它在wordlist中必须检查。再次代替String Hash,创建一个Integer Hash Set。 创建此Integer Hash Set的迭代器。
Iterator it = myTenWordsHashSet.iterator();
在循环中迭代它并检查以下条件:
wordListHashSet.contains(it.next());
如果这是真的,那么你在单词列表中有这个词。
当您正在寻找性能时,使用Integer Hash Maps是个好主意。内部Java处理每个字符串的散列并将其存储在内存中,以便重复访问此类字符串的速度快,比二进制搜索更快,搜索复杂度为O(log n),每次调用元素时几乎为O(1)在词汇表中。
希望有所帮助!
答案 1 :(得分:1)
对于30,000个单词来说,这可能不值得麻烦,但让我们说你有更多,比如说300,000,000个单词,而且仍然只有10个单词可供查找。
在这种情况下,您可以使用Random Access Files在大文件中为每个搜索词进行二进制搜索。 显然,每个搜索步骤都要求您首先找到单词的开头(或下一个单词,实现dependend),这使得它变得更加困难,并且删除所有极端情况超出了可以提供的代码限制这里。但它仍然可以完成,并且肯定会比阅读所有300,000,000个单词更快。
答案 2 :(得分:0)
您可以考虑迭代10个单词集(可能会将其从文件解析为数组),并且对于每个条目,使用二进制搜索算法来查看它是否包含在较大的列表中。二进制搜索应该只采用O(logN),因此在这种情况下,log(30,000)显着快于30,000步。
由于您将对集合中的每个单词重复此步骤一次,因此需要10 * log(30k)
答案 3 :(得分:0)
您可以根据需要进行一些改进。
例如,如果文件保持不变但您的10个字的Set定期更改,则可以将文件加载到另一个Set(HashSet)上。现在你只需要在这个新Set上搜索一个匹配项。这样您的搜索将始终为O(1)。