在某些库代码中,我有一个可以包含 50,000 个或更多项目的列表。
库的调用者可以调用导致将字符串添加到列表中的方法。如何有效地检查所添加字符串的唯一性?
目前,在添加字符串之前,我会扫描整个列表并将每个字符串与要添加的字符串进行比较。当超过 10,000 个项目时,就会出现规模问题。
我将对此进行基准测试,但对洞察力感兴趣。
- 如果我用 Dictionary 替换 List ,当列表增长到 10,000 个项目或更多时,ContainsKey() 会明显更快吗?
- 如果我将唯一性检查推迟到添加所有项目之后,会更快吗?那时我需要对照每个其他元素检查每个元素,仍然是 n^^2 操作。
EDIT
一些基本的基准测试结果。我创建了一个抽象类,它公开了 2 个方法:填充和扫描。 Fill 只是用 n 个项目填充集合(我使用了 50,000 个)。 Scan 扫描列表 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 倍。
这些结果不一定适用于可变长度的字符串、更复杂的对象或不同的集合大小。