我知道在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(使用前将#替换为@)