[回到起点]看看Java HashMap的源码和实现

  刚出来工作的时候,老大要我从文本提取一些数据, 筛选排序什么的,那时我只晓得用ArrayList, 结果事情是做完了,执行却有点慢。老大看代码说我是在写C语言, 让我试试用HashMap处理, 结果是哇,快好多,从此对HashMap很有好感。年复一年的面试, HashTable,HashMap,TreeMap有啥区别啊,为什么那么快啊之类, 每个工程师都会在面试中得到锻炼和成长:p。面试受打击了,可能网上一搜这个面试题,喔原来答案是这个。真去看下源码的人估计不多,老实说笔者最近才仔细拜读-_-,结合搜索的分享的文章,结果发现自己的源码太新了:p JDK1.8的,大多文章还是JDK1.7的,突然想起看过一篇文章关于JDK重写了HashMap为了解决哈希碰撞的事。JDK能对已有老的库能升级也是蛮罕见的事,所以就有了这篇文章。

  •   先看JDK1.7的HashMap为什么快?

  HashMap使用Entry<K,V>[] table保存数据, 每个节点Entry.next指向另外Entry节点, next存在则表示有相同的key哈希, JDK1.7使用链表保存解决冲突。

    static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        int hash;
  HashMap查找快关键的因素是key hashcode在table数组有一个对应的下标。indexFor是精心设计过的,table.length必须为2的整数次幂, 即length-1为奇数, 奇数做位与才可能产生奇数或偶数(偶数位与就都是偶数了), 保证Entry在table数组中的均匀分布。

    final Entry<K,V> getEntry(Object key) {
        if (size == 0) {
            return null;
        }

        int hash = (key == null) ? 0 : hash(key);
        for (Entry<K,V> e = table[<span style="color:#FF0000;">indexFor</span>(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }
    /**
     * Returns index for hash code h.
     */
    static int indexFor(int h, int length) {
        //<span style="color:#FF0000;"> assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2"</span>;
        return <span style="color:#FF0000;">h & (length-1)</span>;
    }
  话说redis,php哈希采用了类似的数据结构, 可能redis的哈希算法可能冲突会小些。

  那哈希冲突会带来什么问题呢?假设我们写个POJO, hashCode()总是返回0,这个POJO作为HashMap key值的就都冲突了,所有的Entry就退化为链表了,查找就是链表的线性效率了,有人恶意造数据造成了冲突,系统查找响应就很慢, 导致DOS拒绝服务。所以JDK1.8就稍微优化了下。


  • JDK1.8 HashMap改进

当哈希冲突的链表达到一定长度(好像是8),就改用红黑树解决保存节点,就算冲突多查找也不会太慢。


虎头蛇尾。。。下班了。。see you very soon。


Cheers



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值