我正在编写一个程序,它将为数据结构添加越来越多的数字或唯一字符串。一旦完成,我后来需要不断检查其中是否存在字符串。
如果我要使用ArrayList,我相信检查某些指定字符串的存在会遍历所有项目,直到找到匹配的字符串(或到达结尾并返回false)。
然而,使用HashMap我知道在常量时间我可以简单地将键用作String并返回任何非null对象,从而使此操作更快。但是,我并不热衷于填充HashMap,其值完全是任意的。是否存在使用散列函数的现成数据结构,但不需要放置值?
答案 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 (概率数据结构)。