检查String是否存在的高效数据结构

时间:2014-05-18 12:42:34

标签: java algorithm data-structures arraylist hashmap

我正在编写一个程序,它将为数据结构添加越来越多的数字或唯一字符串。一旦完成,我后来需要不断检查其中是否存在字符串。

如果我要使用ArrayList,我相信检查某些指定字符串的存在会遍历所有项目,直到找到匹配的字符串(或到达结尾并返回false)。

然而,使用HashMap我知道在常量时间我可以简单地将键用作String并返回任何非null对象,从而使此操作更快。但是,我并不热衷于填充HashMap,其值完全是任意的。是否存在使用散列函数的现成数据结构,但不需要放置值?

4 个答案:

答案 0 :(得分:6)

  

如果我要使用ArrayList,我相信检查某些指定字符串的存在会遍历所有项目,直到找到匹配的字符串

更正,检查项目列表与列表条目数呈线性关系。

  

但是,我并不热衷于填充HashMap,其值完全是任意的

您不必:Java提供HashSet<T>类,非常类似于没有值部分的HashMap

您可以将所有字符串放在那里,然后在恒定时间内检查是否存在其他字符串;

Set<String> knownStrings = new HashSet<String>();
... // Fill the set with strings

if (knownString.contains(myString)) {
    ...
}

答案 1 :(得分:5)

这取决于很多因素,包括你必须输入到该数据结构中的字符串数量(你知道这个数字是提前的,还是有一个基本的想法?),以及你希望命中/未命中率是多少

要使用的非常有效的数据结构是trie或基数树;它们基本上是为此而制造的。有关它们如何工作的说明,请参阅the wikipedia entry(此页面中的基数树定义的后续内容)。有Java实现(其中一个是here;但是我有一组固定的字符串要注入,这就是我使用构建器的原因。)

如果您的字符串数量非常大,那么您不会期望最小的错失率,那么您也可以考虑使用bloom filter;但问题是它是概率性的;但你可以得到“不存在”的快速答案。这里也有Java实现(例如,Guava有一个实现)。

否则,好吧,HashSet ...

答案 2 :(得分:1)

HashSet可能是正确的答案,但如果您选择(为简单起见)搜索列表,将单词连接到带分隔符的String可能更有效:

String wordList = "$word1$word2$word3$word4$...";

然后用分隔符之间的单词创建一个搜索参数:

String searchArg = "$" + searchWord + "$";

然后搜索contains

bool wordFound = wordList.contains(searchArg);

使用StringBuilder构建searchArg可以使效率更高一些。

答案 3 :(得分:0)

正如其他人提到的,HashSet是必经之路。但是,如果大小会很大,并且您可以接受误报(检查用户名是否存在),也可以使用 BloomFilters (概率数据结构)。