【问题标题】:Should I use a `HashSet` or a `TreeSet` for a very large dataset?对于非常大的数据集,我应该使用“HashSet”还是“TreeSet”?
【发布时间】:2015-10-26 08:26:23
【问题描述】:

我需要在数据结构中存储 2 到 1500 万个帐户(长度为 15 的 String),以用于查找和检查唯一性。最初我计划将它们存储在HashSet 中,但我怀疑查找速度会因为散列冲突而变慢,并且最终会比 TreeMap 慢(使用二进制搜索)。

不需要对数据进行排序。我正在使用 Java 7。我有 64G 系统,其中 48G 专用于此应用程序。

这个问题不是HashSet and TreeSet performance test 的重复问题,因为这个问题是关于Set 添加元素 的性能,而这个问题是关于检查现有@ 的性能987654326@ 重复值。

【问题讨论】:

  • 也可以参考this
  • 嗨,Ankuar,谢谢。链接中的性能测试基于已排序的 500K 整数。我有 1000 万个字符串,想了解哈希冲突的可能性。在第二个链接中有提示是 hwlpful。我会尝试将我的观察结果发布回来。
  • 查找用于检查特定字符串是否存在于字符串集中。这是一个独立的 java 程序,不能使用 Redis 之类的东西来存储数据。

标签: java performance hashset treeset


【解决方案1】:

如果您有 48 GB 的专用内存来存储 200 万到 1500 万条记录,那么最好的选择可能是使用 HashMap<Key, Record>,其中您的密钥是 IntegerString,具体取决于您的要求。

只要您为Map 提供足够的内存并具有适当的负载因子,就可以解决哈希冲突。

我建议使用以下构造函数:new HashMap<>(13_000_000);(比您预期的记录数多 30% - 这将由 HashMap 的实现自动扩展为 2^24 单元格)。 告诉您的应用程序这个Map 从一开始就非常大,因此它不需要在您填充它时自动增长。

HashMap 对其成员使用O(1) 访问时间,而TreeMap 使用O(log n) 查找时间,但可以更高效地使用内存并且不需要聪明的散列函数。但是,如果您使用 StringInteger 键,则无需担心设计散列函数,恒定时间查找将是一个巨大的改进。此外,TreeMap / TreeSet 的另一个优点是排序顺序,您说您不在乎;使用HashMap

如果列表的唯一目的是检查唯一帐号,那么我上面所说的一切仍然正确,但正如您在问题中所说,您应该使用 @987654339 @,不是HashMap。性能建议和构造函数参数仍然适用。

延伸阅读:HashSet and TreeSet performance test

【讨论】:

  • 非常感谢。如果是动态增长的数据集,我不知道元素的确切数量,我可以知道什么会更好。数据集可以包含 200 万到 1500 万(确切大小未知)
  • @Mohan 如果你有那么多可用内存,那也没什么区别。如果您的上限与您的内存量相比如此之低,则只需设置最大合理的HashMap - 2^24 位 - 就可以了。
【解决方案2】:

当我们尝试使用适当的初始化参数在 HashMap 中存储 5000 万条记录时,插入开始变慢,尤其是在 3500 万条记录之后。更改为 TreeMap 可提供恒定的插入和检索性能。

观察:对于大型输入集,TreeMap 将提供比 HashMap 更好的性能。对于较小的集合,当然 HashMap 会提供更好的性能。

【讨论】:

  • 您没有询问大约 5000 万条记录,而是询问了大约 1500 万条记录。在某些时候,您需要考虑您的哈希函数以及如果您的密钥只是 String 时发生冲突的可能性,默认实现适用于大多数用途,但可能不适用于 5000 万个字符串。
猜你喜欢
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-10
  • 1970-01-01
  • 2020-06-24
  • 1970-01-01
相关资源
最近更新 更多