【问题标题】:Efficient data structure that checks for existence of String检查字符串是否存在的高效数据结构
【发布时间】:2014-07-06 11:37:44
【问题描述】:
我正在编写一个程序,它将向数据结构中添加越来越多的数字或唯一的字符串。完成此操作后,我稍后需要不断检查其中是否存在字符串。
如果我要使用 ArrayList,我相信检查某些指定字符串是否存在将遍历所有项目,直到找到匹配的字符串(或到达末尾并返回 false)。
但是,使用 HashMap 我知道在恒定时间内我可以简单地将键用作字符串并返回任何非空对象,从而使此操作更快。但是,我并不热衷于填充值完全任意的 HashMap。是否有现成的使用哈希函数但不需要放置值的数据结构?
【问题讨论】:
标签:
java
algorithm
data-structures
arraylist
hashmap
【解决方案1】:
正如其他人提到的那样,HashSet 是要走的路。但是,如果大小会很大并且您可以接受误报(检查用户名是否存在),您也可以使用 BloomFilters(概率数据结构)。
【解决方案2】:
这取决于许多因素,包括您必须输入该数据结构的字符串数量(您是否提前知道数量,或者有一个基本概念?),以及您期望的命中/未命中率是多少.
trie 或基数树是一种非常有效的数据结构;它们基本上就是为此而生的。有关它们如何工作的说明,请参阅the wikipedia entry(基数树定义的后续内容在此页面中)。有 Java 实现(其中一个是 here;但是我有一组固定的字符串要注入,这就是我使用构建器的原因)。
如果您的字符串数量真的很大并且您不希望有最小的未命中率,那么您也可以考虑使用bloom filter;然而,问题在于它是概率性的;但是你可以很快得到“不存在”的答案。这里也有 Java 的实现(例如 Guava 有一个实现)。
否则,好吧,HashSet...
【解决方案3】:
HashSet 可能是正确的答案,但如果您选择(例如,为了简单起见)搜索列表,则将您的单词连接成带分隔符的字符串可能更有效:
String wordList = "$word1$word2$word3$word4$...";
然后在分隔符之间创建一个搜索参数:
String searchArg = "$" + searchWord + "$";
然后搜索,例如,contains:
bool wordFound = wordList.contains(searchArg);
您可以通过使用 StringBuilder 构建 searchArg 来提高效率。
【解决方案4】:
如果我要使用 ArrayList,我相信检查某些指定字符串的存在会遍历所有项目,直到找到匹配的字符串
正确,检查列表中的项目与列表的条目数成线性关系。
但是,我并不热衷于填充值完全任意的 HashMap
您不必这样做:Java 提供了一个 HashSet<T> 类,它非常类似于没有值部分的 HashMap。
您可以将所有字符串放在那里,然后在恒定时间内检查其他字符串是否存在;
Set<String> knownStrings = new HashSet<String>();
... // Fill the set with strings
if (knownString.contains(myString)) {
...
}