【问题标题】:What is the time complexity of initializing an HashSet using a populated ArrayList?使用填充的 ArrayList 初始化 HashSet 的时间复杂度是多少?
【发布时间】:2017-05-23 20:12:57
【问题描述】:

我在网上看到HashSet 使用HashMap 作为其底层数据结构。

HashMap 使用ArrayList 作为其基础数据结构,列表中的每个项目都是LinkedListtree 的对象。

以这种方式初始化HashSet 的时间复杂度是多少?可以是O(1)吗?如果不是,为什么?

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
list.add(2);
list.add(6);
list.add(0);
HashSet<Integer> set = new HashSet<>(list);

【问题讨论】:

  • 您的标题是 HashMap,但您的代码演示了如何初始化 HashSet
  • 感谢您指出。我已经更新了问题。

标签: java performance collections


【解决方案1】:

HashMap 不使用ArrayList 作为其底层数据结构。

HashMap 维护一个由原始数组构建的哈希表,并使用链表或树的混合策略来处理冲突。您可以通过检查 source code for java.util.HashMap 来看到这一点。

由于要构建哈希表,您需要在每个条目上调用哈希函数以确定哈希位置,最小界限是 O(N)。最坏的情况是病态分布的密钥(例如,每个密钥都是一个冲突),这将比 O(N) 差得多。由于 Java 8 实现在最坏情况下会降级为平衡树而不是链表,因此最坏情况下的运行时间将是 O(N log N)。 (在以前使用线性探测的 Java 版本中,我认为最坏的情况是 O(N²))。

【讨论】:

  • java8 中的默认实现不使用探测,它使用链表来存储小桶(最多约 8 个项目),使用树来存储更大的桶。
  • @k5_:确实如此。看起来 Java 8 的实现比 Java 7 或更早版本要复杂得多。我已经更新了我的答案,谢谢。
  • @DanielPryden,感谢您的解释。我会研究源代码。
【解决方案2】:

您的List 可以包含n 数量的对象,这些对象可能都是重复的或唯一的或混合的。

HashSet 集合的属性是它不包含重复的对象。

因此,遍历List 并将每个对象添加到HashSet 的时间复杂度为O(n)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-01
    • 2019-02-02
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多