【源码分析】hashmap中的红黑树是如何进行排序的

JDK1.8对HashMap进行了性能升级,其底层数据结构为数组+链表,当hash碰撞形成链表时,JDK1.8对链表部分进行优化,采用红黑树形式,时间复杂度从O(N)降为O(lgn)。红黑树形成和变回链表有规则,还介绍了自动排序及无Comparable接口的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用过jdk1.8的童鞋们应该知道,jdk1.8对hashmap又进行了性能上的升级,虽然对于我们这些常年使用map只含有几十个key的业务员来说(斜眼笑),貌似没什么影响,但是,我们还是需要去了解一下的。

首先我们知道,hashmap的底层数据结构是数组+链表。

只有当hash发生碰撞时,才会形成链表,所以对链表部分进行了优化。

假设一个人的名字(String)作为key,他叫Lebron,他有1w个物品。

如果要找到他的女朋友,girlfriend.class,(假设只能有一个女朋友)那么找到她的时间复杂度为O(N)。

jdk1.8对这部分链表进行了优化,采用红黑树的形式,时间复杂度为O(lgn)。不过红黑树的形成是有一定规则的哟~

static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD = 6;

源码中这2个参数代表着,当链表大于8时,才进行红黑树排序。

当操作tree以后,tree的size小于6,重新变为链表结构。

今天我们学习一下是怎么帮我们进行自动排序的,因为树形结构是需要实现Comparable的才能进行排序的。

static Class<?> comparableClassFor(Object x) {
    if (x instanceof Comparable) {
        Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
        if ((c = x.getClass()) == String.class) // bypass checks
            return c;
        if ((ts = c.getGenericInterfaces()) != null) {
            for (int i = 0; i < ts.length; ++i) {
                if (((t = ts[i]) instanceof ParameterizedType) &&
                    ((p = (ParameterizedType)t).getRawType() ==
                     Comparable.class) &&
                    (as = p.getActualTypeArguments()) != null &&
                    as.length == 1 && as[0] == c) // type arg is c
                    return c;
            }
        }
    }
    return null;
}

comparableClassFor方法是用来寻找此类是否有实现Comparable接口(它先判断了String,String类也实现了Comparable)。

 

static int compareComparables(Class<?> kc, Object k, Object x) {
    return (x == null || x.getClass() != kc ? 0 :
            ((Comparable)k).compareTo(x));
}
compareComparables方法是在使用过comparableClassFor后才使用的,因为第一步已经获取到了比较器,那么就可以快乐的将链表里的object逐个去比较啦。

那么问题来了,这个class不是String类,也没有实现Comparable接口怎么办呢。

终极解决方案!

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;
}

通过class类名来进行string的排序,龟龟~

 

 

 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值