背景:假设有两个对象,分别是 stu 和 teach(都没有实现 Comparable 接口),将它们添加进去 HashMap 里,假设这两个对象发生哈希冲突,那么红黑树怎么判断它们谁在左谁在右?依据是什么?
当两个对象 stu
和 teach
的哈希值相同,且它们没有实现 Comparable
接口时,Java 8 的 HashMap
会使用 tieBreakOrder
方法来决定它们在红黑树中的位置。
/**
* Tie-breaking utility for ordering insertions when equal
* hashCodes and non-comparable. We don't require a total
* order, just a consistent insertion rule to maintain
* equivalence across rebalancings. Tie-breaking further than
* necessary simplifies testing a bit.
*/
static int tieBreakOrder(Object a, Object b) {
int d;
if (a == null || b == null ||
(d = a.getClass().getName().
compareTo(b.getClass().getName())) == 0)
d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
-1 : 1);
return d;
}
tieBreakOrder
方法首先比较两个对象的类名,如果类名相同,则使用 System.identityHashCode
方法来比较它们的内存地址。
具体来说,tieBreakOrder
方法会执行以下步骤:
- 比较类名: 如果两个对象的类名不同,则根据类名的字典序来决定谁在左谁在右。
- 比较内存地址: 如果两个对象的类名相同,则使用
System.identityHashCode
方法来比较它们的内存地址。内存地址较小的对象会被放在左边,内存地址较大的对象会被放在右边。
因此,stu
和 teach
在红黑树中的位置取决于它们的类名和内存地址。如果它们的类名相同,则内存地址较小的对象会被放在左边,内存地址较大的对象会被放在右边。
需要注意的是,tieBreakOrder
方法只是 HashMap
在处理哈希冲突时的一种策略。如果两个对象的哈希值相同,但它们的类名和内存地址也相同,那么它们会被视为同一个对象,并且只会存储一次。