源码分析HashMap初探

HashMap可以存储键值对,是数据存储时经常使用到的一个集合类。经常使用也就要好好研究下喽。HashMap类设计巧妙,水平有限,只能简单分析下,尝做一帖记录。


源码分析:

实现了Map,Cloneable,Serializable接口:

public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable

HashMap中的关键属性:

static final int DEFAULT_INITIAL_CAPACITY = 16;  //初始容量大小
transient Entry[] table;//存储元素的实体数组 
transient int size;//存放元素的个数 
int threshold; //临界值  当实际大小超过临界值时,会进行扩容threshold = 加载因子*容量
final float loadFactor; //加载因子
transient int modCount;//被修改的次数

loadFactor加载因子是表示Hash表中元素的填满的程度

构造方法:

public HashMap(int initialCapacity, float loadFactor) {
        //确保数字合法
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                              initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                              loadFactor);

        // Find a power of 2 >= initialCapacity
        int capacity = 1;   //初始容量
        while (capacity < initialCapacity)   //确保容量为2的n次幂,使capacity为大于initialCapacity的最小的2的n次幂
            capacity <<= 1;

        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);
        table = new Entry[capacity];
       init();
   }

    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
   }

    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
       init();
    }

HashMap的get,put 操作:

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


    public V put(K key, V value) {
    // 若“key为null”,则将该键值对添加到table[0]中。
        if (key == null)
            return putForNullKey(value);
  //若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。
        int hash = hash(key.hashCode());
        //搜索指定hash值在对应table中的索引
        int i = indexFor(hash, table.length);
 //循环遍历Entry数组,若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出!
        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;
    }

再上个HashMap的小例子:

进行了HashMap的简单尝试

package javaCollection;

import java.util.Map;
import java.util.HashMap;
import java.util.Hashtable;

public class HashMapDemo {

    /**
     * 实现哈希表的数据结构
     * 
     *  Hashtable 不可以存入null 键和null 值;但是HashMap 可以存入null 键和null 值。
        hashtable 是线程安全Map 实现;但HashMap 是线程不安全的实现类。所以HashMap 性能比较高点。
     * @param args
     */
    public static void main(String[] args)
    {
        Map<String,String> hash  = new HashMap<String, String>() ;

//        给HashMap 集合存入null键或者null值
        hash.put("111", null) ; 
        hash.put(null, "1112") ;
//        取出的结果为 1112
        System.out.println(hash.get(null));
        Map<String,String> table = new Hashtable<String, String>() ; 
//        下面的代码会出现运行异常:NullPointerException
//       table.put("111", null) ;   HashTable下不能插入null的值
//       table.put(null, "1112") ;  HashTable不能插入null的键
        table.put("pi","11" );
        System.out.println(table.get("pi"));
    }
}

记得上次碰到HashMap的扩容实现问题:

总的而言:

当添加元素后,数组的长度超过阈值继而进行扩容:

  • 1.初始容量为16,阈值12

  • 2.计算新的数组长度并初始化

    • 新的长度为原来长度*2

    • 新的阈值为新的长度*loadFactor

  • 3.将原来的数据迁移到新的数组

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值