繁体   English   中英

.NET:如何有效地检查List <string>中50,000项的唯一性?

[英].NET: How to efficiently check for uniqueness in a List<string> of 50,000 items?

在某些库代码中,我有一个可以包含50,000个或更多项的List。

库的调用者可以调用导致字符串添加到列表的方法。 如何有效地检查要添加的字符串的唯一性?

目前,在添加字符串之前,我扫描整个列表并将每个字符串与要添加的字符串进行比较。 这开始显示超过10,000个项目的规模问题。

我将对此进行基准测试,但对洞察力感兴趣。

  • 如果我用List <>替换List <>,那么随着列表增长到10,000个项目以及更高,ContainsKey()会更快吗?
  • 如果我推迟了所有项目添加后的唯一性检查,它会更快吗? 在那一点上,我需要检查每个元素与每个其他元素,仍然是一个n ^^ 2操作。

编辑

一些基本的基准结果。 我创建了一个抽象类,它暴露了两种方法:Fill和Scan。 填充只用n个项目填充集合(我用了50,000)。 扫描扫描列表m次(我使用5000)以查看是否存在给定值。 然后我为List构建了该类的实现,为HashSet构建了另一个实现。

使用的字符串长度统一为11个字符,并通过抽象类中的方法随机生成。

一个非常基本的微观基准。

Hello from Cheeso.Tests.ListTester
filling 50000 items...
scanning 5000 items...
Time to fill: 00:00:00.4428266
Time to scan: 00:00:13.0291180

Hello from Cheeso.Tests.HashSetTester
filling 50000 items...
scanning 5000 items...
Time to fill: 00:00:00.3797751
Time to scan: 00:00:00.4364431

因此,对于该长度的字符串,当扫描唯一性时,HashSet比List快大约25倍。 此外,对于此大小的集合,在向集合添加项目时,HashSet对List没有任何惩罚。

结果很有趣,无效。 为了获得有效的结果,我需要进行预热间隔,多次试验,随机选择实施。 但我相信这只会略微改变这一点。

感谢大家。

EDIT2

在添加随机化和多重试验之后,HashSet在这种情况下始终优于List,大约20倍。

这些结果不一定适用于可变长度,更复杂对象或不同集合大小的字符串。

您应该使用HashSet<T>类,它专门为您正在进行的操作而设计。

使用HashSet<string>而不是List<string> ,它应该可以很好地扩展。

从我的测试中, HashSet<string>List<string>相比没有时间:)

可能偏离主题,但如果您想以独立于语言的方式扩展非常大的独特字符串集(数百万+),您可以查看Bloom Filters

我已经读过字典<>被实现为关联数组。 在某些语言中(不一定与.NET有关),字符串索引存储为树结构,根据节点中的字符在每个节点上分叉。 请参阅http://en.wikipedia.org/wiki/Associative_arrays

类似的数据结构是由Aho和Corasick在1973年设计的(我认为)。 如果在这样的结构中存储50,000个字符串,那么重要的不是您存储的字符串数量。 更重要的是字符串的长度 如果它们的长度大致相同,那么您可能永远不会看到查找速度减慢,因为搜索算法在运行时相对于您要搜索的字符串的长度是线性的。 即使对于红黑树或AVL树,搜索运行时更多地取决于要搜索的字符串的长度,而不是索引中的元素数。 但是,如果您选择使用散列函数实现索引键,则现在会产生散列字符串的成本(将为O(m),m =字符串长度)以及索引中字符串的查找,其中可能是O(log(n))的顺序,n =索引中元素的数量。

编辑:我不是.NET大师。 其他更有经验的人建议另一种结构。 我会接受他的话。

edit2:你的分析对比较唯一性有点偏僻。 如果你使用散列结构或字典,那么由于我在上面发布的推理,它不会是O(n ^ 2)操作。 如果继续使用列表,那么你是正确的,它是O(n ^ 2)*(集合中字符串的最大长度),因为你必须每次检查列表中的每个元素。

Contains(T)功能不适合你吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM