【问题标题】:Why HashMap uses TreeNode for not Comparable keys?为什么 HashMap 使用 TreeNode 作为不可比较的键?
【发布时间】:2017-12-20 09:38:55
【问题描述】:

我知道在 Java 8 中 HashMap 已针对分布不佳的 hashCode 进行了优化。并且在超过阈值的情况下,它会将存储桶中的节点从链表重建为树。同样是stated,这种优化不适用于不可比较的键(至少性能没有提高)。在下面的示例中,我将 not Comparable 键放入 HashMap

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

class Main {
    public static void main(String[] args) throws InterruptedException {
        Map<Key, Integer> map = new HashMap<>();

        IntStream.range(0, 15)
                .forEach(i -> map.put(new Key(i), i));

        // hangs the application to take a Heap Dump
        TimeUnit.DAYS.sleep(1);
    }
}

final class Key {
    private final int i;

    public Key(int i) {
        this.i = i;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Key key = (Key) o;
        return i == key.i;
    }

    @Override
    public int hashCode() {
        return 1;
    }
}

但是检查堆转储显示节点被重新排列成树。

我的问题是,如果节点不会提高性能,为什么要在树中重建节点?在这种情况下,节点会根据哪些标准进行比较,以确定哪个键应该是右节点,哪个是左节点?

【问题讨论】:

    标签: java java-8 hashmap


    【解决方案1】:

    我认为你有点误解了那个答案的意思。 Comparable 不是需要,它只是在哈希值相等时可能使用的优化 - 以便决定将条目移动到哪里 - 向左或向右 (perfectly balanced red-black tree node)。稍后如果键是可比较的,它将使用System.identityHashcode

    找出哪个键应该是右节点,哪个是左节点

    它向右 - 较大的键向右,但树可能需要平衡。 一般您可以查找Tree 如何变成perfectly balanced red black tree 的确切算法,例如here

    【讨论】:

    • Afaik 它不使用身份哈希码,只使用密钥对象的哈希码。
    • @JornVernee 它确实。请参阅HashMap 中的tieBreakOrder 方法
    • @Eugene 这是当哈希码相等时的后备(这不一定是哈希冲突的情况,尽管我猜在这个例子中)。如果您查看它在 putTreeVal 中的使用位置,您会看到它在此之前尝试使用密钥的哈希码。
    • 对不起,我误解了你。 @Eugene 是对的。我忘记了tieBreakOrder。它首先通过自己的哈希计算dir,然后使用Comparable,最后使用System.identityHashCode,这是一个全球唯一的哈希码。
    • @ArtemPetrov 说得好!这是对它的解释:yermilov.github.io/blog/2017/02/24/…
    猜你喜欢
    • 2016-06-04
    • 1970-01-01
    • 2016-02-14
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    相关资源
    最近更新 更多