Java HashMap深入分析

hash存储过程:
初始化:
1: 首先初始化hash结构, 初始化桶的个数和加载因子.
put(k, v):
1: 通过k的hashcode值再hash的得到h, 再和桶的长度进行indexFor(int h, int length),得出桶的index.
2: 相当于在桶的中寻找出合适的位置.
3: 在这个位置放下这个对象:table[i] = Entry(k, v), Entry实际上是一个链表
4: 将数据放在链表的第一个位置. table[i].next =new Entry(k, v, oldValue).
5: 如果数据增加到临界值(初始大小*加载因子), 则需要重新创建以前2倍大小的桶(new_table=2*table).
6: 然后将table数据再拷贝到newtable中, 当然拷贝的只是table的索引.
get(k):
1: 通过k的hashcode值再hash的得到h和桶的长度(length). 再进行indexFor(int h, int length),得出桶的index.
2: 取出桶中的数据Entry,由于Entry是一个链表所以需要遍历出k的hash值和key都是相等的数据.

//HashMap
public HashMap() {
		  //即上文说的加载因子(默认0.75)
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        //默认大小(12 = 16 * 0.75)
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        //初始化桶的个数
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }
    
//put方法:
public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
        //hashCode=> hash
    int hash = hash(key.hashCode());
    //hash => index
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
    //这个里面是特殊处理,如果存在旧数据, 则用的新的替换掉
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

 void addEntry(int hash, K key, V value, int bucketIndex) {
     //取出以前数据
    Entry<K,V> e = table[bucketIndex];
    //对新的数据封装.
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);

    if (size++ >= threshold)
    //如果容量过大应该重建table结构.
        resize(2 * table.length);
}

void resize(int newCapacity) {
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    if (oldCapacity == MAXIMUM_CAPACITY) {
        threshold = Integer.MAX_VALUE;
        return;
    }

    Entry[] newTable = new Entry[newCapacity];
    transfer(newTable);
    table = newTable;
    threshold = (int)(newCapacity * loadFactor);
}

//get
public V get(Object key) {
    if (key == null)
        return getForNullKey();
    int hash = hash(key.hashCode());
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
            return e.value;
    }
    return null;
}


转载于:https://my.oschina.net/u/139611/blog/182679

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值