jdk7下HashMap源码分析

package java.util;
import java.io.*;

/**
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 *
 * @author  Doug Lea
 * @author  Josh Bloch
 * @author  Arthur van Hoff
 * @author  Neal Gafter
 * @see     Object#hashCode()
 * @see     Collection
 * @see     Map
 * @see     TreeMap
 * @see     Hashtable
 * @since   1.2
 */
 
 
 /**
 * 1、为什么加载因子越大,HashMap的查询效率越慢?
 * 加载因子越大,发生碰撞的可能性越大。
 *
 *
 * 2、Map m = Collections.synchronizeMap(hashMap)
 * 3、HashMap的迭代器(Iterator)是fail-fast迭代器
 * 
 *
 */
 
 

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

    //位移算法(1的二进制向左移动4位) 0000 0001 ——> 0001 0000 就是结果16 
	//初始容量
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
	  

    //最大容量(哈希数组的最大值)
    static final int MAXIMUM_CAPACITY = 1 << 30;
	

    //初始加载因子
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
	

    //Map接口里有一个内部接口Entry<K,V>
	//它是Map存放key-value映射的数据结构
    static final Entry<?,?>[] EMPTY_TABLE = {
   };
	

    //Entry数组(哈希数组),每一个Entry的数据结构就是一个单向链表
	//transient关键字表明该对象不会被序列化
    transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
	

    //键值对的数量
    transient int size;
	

    //临界值  
	//threshold = capacity * loadFactor;
    int threshold;
	
	
    //加载因子
    final float loadFactor;
	

    //记录Hashmap被修改的次数
    transient int modCount;
	

    //本地修改默认临界值
    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;

    
	
	//?????
    private static class Holder {
   

        static final int ALTERNATIVE_HASHING_THRESHOLD;

        static {
   
            String altThreshold = java.security.AccessController.doPrivileged(
                new sun.security.action.GetPropertyAction(
                    "jdk.map.althashing.threshold"));

            int threshold;
            try {
   
                threshold = (null != altThreshold)
                        ? Integer.parseInt(altThreshold)
                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;

                // disable alternative hashing if -1
                if (threshold == -1) {
   
                    threshold = Integer.MAX_VALUE;
                }

                if (threshold < 0) {
   
                    throw new IllegalArgumentException("value must be positive integer.");
                }
            } catch(IllegalArgumentException failed) {
   
                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
            }

            ALTERNATIVE_HASHING_THRESHOLD = threshold;
        }
    }

    
    transient int hashSeed = 0;

    //构造函数*******
	//参数:容量、加载因子
	//当容量小于0、加载因子小于0或不是一个数字时会报非法参数异常
	//当容量大于最大容量时,则容量等于最大容量
    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);

        this.loadFactor = loadFactor;
        threshold = initialCapacity;
        //?????
		init();
    }

    //构造函数
	//参数:容量
	//加载因子为默认加载因子(0.75f)
    public HashMap(int initialCapacity) {
   
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    //默认构造函数
	//容量为默认初始容量(16)
	//加载因子为默认加载因子(0.75f)
    public HashMap() {
   
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    //构造函数
	//参数:Map<? extends K, ? extends V>
    public HashMap(Map<? extends K, ? extends V> m) {
   
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
                      DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
        //初始化HashMap属性
		inflateTable(threshold);
		//把参数Map添加进当前Map中
        putAllForCreate(m);
    }
	
	//Integer.highestOneBit(number)
	//取number这个数的二进制形式最左边的最高一位且高位后面全部补零,最后返回int型的结果
    private static int roundUpToPowerOf2(int number) {
   
        //14  13 0000 1101 0001 0000 结果:16
		//2   1  0000 0001 0000 0010 结果:2
		//32  31 0001 1111 0010 0000 结果:32
        return number >= MAXIMUM_CAPACITY
                ? MAXIMUM_CAPACITY
                : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
    }
	

    //初始化当前Map的属性
    private void inflateTable(int toSize) {
   
        //根据当前临界值上浮得到新的容量
        int capacity = roundUpToPowerOf2(toSize);
		//根据新的容量重新计算临界值
        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
		//初始化table(为空)
        table = new Entry[capacity];
		//初始化hashSeed为0???
        initHashSeedAsNeeded(capacity);
    }


    //?????
    void init() {
   
    }

	
    //初始化hashSeed?????
    final boolean initHashSeedAsNeeded(int capacity) {
   
        boolean currentAltHashing = hashSeed != 0;
        boolean useAltHashing = sun.misc.VM.isBooted() &&
                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
        boolean switching = currentAltHashing ^ useAltHashing;
        if (switching) {
   
            hashSeed = useAltHashing
                ? sun.misc.Hashing.randomHashSeed(this)
                : 0;
        }
        return switching;
    }
	
	//该方法主要是将Object转换成一个整型,配合indexFor方法找到在数组中的下标位置	
    final int hash(Object k) {
   
        int h = hashSeed;
        if (0 != h && k instanceof String) {
   
			//stringHash32():Java实现的哈希算法
			
            return sun.misc.Hashing.stringHash32((String) k);
        }
        //对key的hashCode进行扰动计算
        //当两个hashcode高位不同低位相同时会发生碰撞
        //扰动计算就是使这两个hashcode运算后低位不同
		//^:位异或运算 101和100结果为101
        h ^= k.hashCode();
		
        //>>>:无符号右移
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
	
	//对HashMap的容量进行取模(取余)确定数组下标
    //位与计算
    static int indexFor(int h, int length) {
   
		//&:按位与计算
		//h % 2^n = h & (2^n – 1)
        return h & (length-1);
    }

    //获取HashMap的大小
    public int size() {
   
        return size;
    }

    //判断HashMap是不是空
    public boolean isEmpty() {
   
        return size == 0;
    }

    //根据key值获取value
    public V get(Object key) {
   
        if (key == null)
            return getForNullKey();
		//根据key值获取当前HashMap中的Entry<K,V>
        Entry<K,V> entry = getEntry(key);
		//entry.getValue():Map接口中的方法
        return null == entry ? null : entry.getValue();
    }

    //获取key值为null的value值
    private V getForNullKey() 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值