HashMap 中处理哈希冲突,红黑树对于没有实现 Comparable 接口的 Key 处理

lyraUU / 2024-08-11 / 原文

背景:假设有两个对象,分别是 stu 和 teach(都没有实现 Comparable 接口),将它们添加进去 HashMap 里,假设这两个对象发生哈希冲突,那么红黑树怎么判断它们谁在左谁在右?依据是什么?

​ 当两个对象 stuteach 的哈希值相同,且它们没有实现 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 方法会执行以下步骤:

  1. 比较类名: 如果两个对象的类名不同,则根据类名的字典序来决定谁在左谁在右。
  2. 比较内存地址: 如果两个对象的类名相同,则使用 System.identityHashCode 方法来比较它们的内存地址。内存地址较小的对象会被放在左边,内存地址较大的对象会被放在右边。

​ 因此,stuteach 在红黑树中的位置取决于它们的类名和内存地址。如果它们的类名相同,则内存地址较小的对象会被放在左边,内存地址较大的对象会被放在右边。

​ 需要注意的是,tieBreakOrder 方法只是 HashMap 在处理哈希冲突时的一种策略。如果两个对象的哈希值相同,但它们的类名和内存地址也相同,那么它们会被视为同一个对象,并且只会存储一次。