hashMap的实现原理

面试的时候经常被问到hashmap的实现,故根据源码,以及网上的一些资料整理了以下笔记,以便以后查阅,如有不正确之处,还请各位多多指教。


我们知道数组存储空间连续,占用内存严重,而且空间复杂度大,它查找速度快,但是插入和删除慢,而链表存储空间离散,占用内存宽松,空间复杂度小,时间复杂度大,查找慢,但是插入和删除快。


根据数组和链表的特点,我们结合这两者的优点,所以产生了hash table,下图是hash table的结构





上图引用http://blog.csdn.net/vking_wang/article/details/14166593


初始化


当我们new 一个hashMap时,会创建一个Entry[],Entry 里存储的数据是一个链表结构,里面有四个变量,int hash,Entry next,Object key,Object value;  hash是哈希值,next为指向下一个Entry,key和value则是键值对。


向hashMap里put数据


put(key,value)时,根据hash(key),算出hash值,用该hash值与Entry[]的长度取模,得到一个值index,这个index则为存放数据的下标地址,既Entry的某个下标。

根据hash值,如果发现key有相同的值,则新值会取代旧值,并返回旧值(public Object put(key,value);如果key不重复,则根据index值找到对应的Entry,把旧的Entry作为新Entry的next。

以下是部分源码:


public Object put(Object obj, Object obj1)
    {
        if(obj == null)
            return putForNullKey(obj1);
        int i = hash(obj);
        int j = indexFor(i, table.length);
        for(Entry entry = table[j]; entry != null; entry = entry.next)
        {
            Object obj2;
            if(entry.hash == i && ((obj2 = entry.key) == obj || obj.equals(obj2)))
            {
                Object obj3 = entry.value;
                entry.value = obj1;
                entry.recordAccess(this);
                return obj3;
            }
        }
       modCount++;
        addEntry(i, obj, obj1, j);
       return null;
    }

void addEntry(int i, Object obj, Object obj1, int j)
    {
        if(size >= threshold && null != table[j])
        {
            resize(2 * table.length);
            i = null == obj ? 0 : hash(obj);
            j = indexFor(i, table.length);
        }
        createEntry(i, obj, obj1, j);
    }


void createEntry(int i, Object obj, Object obj1, int j)
    {
        Entry entry = table[j];
        table[j] = new Entry(i, obj, obj1, entry);
        size++;
    }

Entry(int i, Object obj, Object obj1, Entry entry)
        {
            value = obj1;
            next = entry;
            key = obj;
            hash = i;
        }


向hashMap里get数据


原理和向hashMap数据类似



public Object get(Object obj)
    {
        if(obj == null)
        {
            return getForNullKey();
        } else
        {
            Entry entry = getEntry(obj);
            return null != entry ? entry.getValue() : null;
        }
    }


 private Object getForNullKey()
    {
        if(size == 0)
            return null;
        for(Entry entry = table[0]; entry != null; entry = entry.next)
            if(entry.key == null)
                return entry.value;

        return null;
    }

 final Entry getEntry(Object obj)
    {
        if(size == 0)
            return null;
        int i = obj != null ? hash(obj) : 0;
        for(Entry entry = table[indexFor(i, table.length)]; entry != null; entry = entry.next)
        {
            Object obj1;
            if(entry.hash == i && ((obj1 = entry.key) == obj || obj != null && obj.equals(obj1)))
                return entry;
        }

        return null;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值