为什么 HashMap 使用 TreeNode 作为不可比较的键?

2023-12-29

我知道在Java 8中HashMap针对分布不良进行了优化hashCode。当超过阈值时,它将存储桶中的节点从链表重建为树。也正是stated https://stackoverflow.com/a/45114990/8088193这种优化不适用于不可比较的键(至少性能没有提高)。在下面的例子中我没有放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;
    }
}

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

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


我认为您有点误解了这个答案的意思。Comparable is not needed,这只是当哈希值相等时可能使用的优化 - 为了决定将条目移动到左侧或右侧(perfectly balanced red-black tree node)。稍后如果钥匙是not可比较,它将使用System.identityHashcode.

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

它向右 - 较大的键向右,但树可能需要平衡。一般来说你可以查找具体的算法Tree成为一个perfectly balanced red black tree, like here https://en.wikipedia.org/wiki/Red%E2%80%93black_tree

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 HashMap 使用 TreeNode 作为不可比较的键? 的相关文章

随机推荐