【问题标题】:Is iterating through a TreeSet slower than iterating through a HashSet in Java?遍历 TreeSet 是否比遍历 Java 中的 HashSet 慢?
【发布时间】:2013-11-16 21:06:18
【问题描述】:

我正在运行一些基准测试。我的一项测试取决于顺序,因此我为此使用了 TreeSet。我的第二个测试没有,所以我使用了 HashSet。

我知道 TreeSet 的插入速度较慢。但是遍历所有元素呢?

【问题讨论】:

  • 为什么不使用 timer 并自己找到它?
  • 考虑到 HashSet 使用哈希表,我会说是的。

标签: java iteration hashset treeset


【解决方案1】:

如果您希望以(几乎)HashSet 的性能进行稳定排序,请使用LinkedHashSet。你仍然会得到恒定时间的操作,而我假设 TreeSet 会得到对数时间。

【讨论】:

    【解决方案2】:

    来自类似帖子 (Hashset vs Treeset):

    HashSet 比 TreeSet 快得多(对于添加、删除和包含等大多数操作而言,HashSet 是常数时间与日志时间),但不提供像 TreeSet 那样的排序保证。

    哈希集:

    • 类为基本操作(添加、删除、包含和大小)提供恒定的时间性能。
    • 它不保证元素的顺序会随着时间的推移保持不变
    • 迭代性能取决于HashSet的初始容量负载因子
      • 接受默认负载因子是相当安全的,但您可能希望指定一个大约是您期望集合增长到的大小的两倍的初始容量。

    树集:

    • 保证基本操作(添加、删除和包含)的 log(n) 时间成本
    • 保证 set 的元素将被排序(升序、自然或您通过其构造函数指定的排序)
    • 不提供任何迭代性能的调整参数
    • 提供了一些方便的方法来处理有序集,例如first()last()headSet()tailSet()

    要点:

    • 两者都保证元素的无重复集合
    • 通常将元素添加到 HashSet,然后将集合转换为 TreeSet 以进行无重复的排序遍历会更快。
    • 这些实现都不同步。也就是说,如果多个线程同时访问一个集合,并且至少有一个线程修改了该集合,则它必须在外部同步。
    • LinkedHashSet 在某种意义上介于HashSetTreeSet 之间。实现为带有链表的哈希表,但是它提供了与 TreeSet 保证的排序遍历不同的插入排序迭代

    所以用法的选择完全取决于你的需要,但我觉得即使你需要一个有序的集合,那么你仍然应该更喜欢 HashSet 来创建 Set 然后将其转换为 TreeSet。

    • 例如Set<String> s = new TreeSet<String>(hashSet);

    【讨论】:

    • 这是一个非常彻底的答案,但似乎根本没有解决 OP 的实际问题......
    • 嗯,我不同意。这个答案清楚地解决了 HashSet 和 TreeSet 之间的迭代,尽管它的含义可能比 OP 想要的更模糊。来自“重要点”部分的第二个要点:“向 HashSet 添加元素然后将集合转换为 TreeSet 以进行无重复排序遍历通常更快。”
    • 好吧,答案的那部分完全是错误的。首先添加到 HashSet 的开销有什么意义?如果您要在事后复制到 TreeSet,这完全是无用的开销(好吧,除非您在原始集合中有大量重复)。
    【解决方案3】:

    TreeSets 内部使用TreeMaps,它们是Red Black TreesBST 的特殊类型)。

    BST中序遍历是O(n)

    HashSets 在内部使用HashMaps,它使用array 来保存Entry 对象。

    这里的遍历也应该是O(n)

    除非您编写基准测试,否则很难证明哪个更快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-08
      • 1970-01-01
      • 1970-01-01
      • 2017-03-04
      • 2014-10-03
      • 2019-12-14
      • 1970-01-01
      • 2020-06-17
      相关资源
      最近更新 更多