HashMap解惑

  点击上方蓝字  中科软之java项目开发综合知识

本公众号主要推送javaweb开发相关技术,基础知识点,同时会深入剖析复杂的问题,分享一些优秀的框架,大型项目经验,当今最流行的Javaweb技术,热点科技新闻,招聘信息等等。点击上方的蓝字,这样您每天可以看到更多的java知识和资讯!完全是免费订阅,请放心关注。

原文连接:http://wely.iteye.com/blog/2334552

HashMap中有一些我们容易忽视的点

1. 关于key的hash和equals

Java代码  

1. public V put(K key, V value) {  

2.         if (table == EMPTY_TABLE) {  

3.             inflateTable(threshold);  

4.         }  

5.         if (key == null)  

6.             return putForNullKey(value);  

7.         int hash = hash(key);  

8.         int i = indexFor(hash, table.length);  

9.         for (Entry<K,V> e = table[i]; e != null; e = e.next) {  

10.            Object k;  

11.            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  

12.                V oldValue = e.value;  

13.                e.value = value;  

14.                e.recordAccess(this);  

15.                return oldValue;  

16.            }  

17.        }  

18.  

19.        modCount++;  

20.        addEntry(hash, key, value, i);  

21.        return null;  

22.    }  

 由上述代码知道,hash值是用来确定bucketIndex,equals是用来和链表上的值比较,因此对于key是自定义的类,强烈建议重写hashCode和equals方法。此处也是容易引起内存泄露的点。

下面摘抄一段JDK里面的注释,

Java代码  

1. /** 

2.      * Returns a hash code value for the object. This method is 

3.      * supported for the benefit of hash tables such as those provided by 

4.      * {@link java.util.HashMap}. 

5.      * <p> 

6.      * The general contract of {@code hashCode} is: 

7.      * <ul> 

8.      * <li>Whenever it is invoked on the same object more than once during 

9.      *     an execution of a Java application, the {@code hashCode} method 

10.     *     must consistently return the same integer, provided no information 

11.     *     used in {@code equals} comparisons on the object is modified. 

12.     *     This integer need not remain consistent from one execution of an 

13.     *     application to another execution of the same application. 

14.     * <li>If two objects are equal according to the {@code equals(Object)} 

15.     *     method, then calling the {@code hashCode} method on each of 

16.     *     the two objects must produce the same integer result. 

17.     * <li>It is <em>not</em> required that if two objects are unequal 

18.     *     according to the {@link java.lang.Object#equals(java.lang.Object)} 

19.     *     method, then calling the {@code hashCode} method on each of the 

20.     *     two objects must produce distinct integer results.  However, the 

21.     *     programmer should be aware that producing distinct integer results 

22.     *     for unequal objects may improve the performance of hash tables. 

23.     * </ul> 

24.     * <p> 

25.     * As much as is reasonably practical, the hashCode method defined by 

26.     * class {@code Object} does return distinct integers for distinct 

27.     * objects. (This is typically implemented by converting the internal 

28.     * address of the object into an integer, but this implementation 

29.     * technique is not required by the 

30.     * Java<font size="-2"><sup>TM</sup></font> programming language.) 

31.     * 

32.     * @return  a hash code value for this object. 

33.     * @see     java.lang.Object#equals(java.lang.Object) 

34.     * @see     java.lang.System#identityHashCode 

35.     */  

36.    public native int hashCode();  

 

 

2. rehash的条件

Java代码  

1. void addEntry(int hash, K key, V value, int bucketIndex) {  

2.         if ((size >= threshold) && (null != table[bucketIndex])) {  

3.             resize(2 * table.length);  

4.             hash = (null != key) ? hash(key) : 0;  

5.             bucketIndex = indexFor(hash, table.length);  

6.         }  

7.   

8.         createEntry(hash, key, value, bucketIndex);  

9.     }  

 if条件告诉我们rehash的条件要同时满足两个:map中元素个数不小于阀值即容量*负载因子,对应的bucketIndex处有元素。

 另外,如下代码作备忘,

Java代码  

1. static int indexFor(int h, int length) {  

2.         // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";  

3.         return h & (length-1);  

4.     }  

 

3. 可以插入(null, null)吗

Java代码  

1. Map<String, String> map = new HashMap<String, String>();  

2.         map.put(nullnull);  

3.         System.out.println(map.size()); // 1  

4.   

5. private V putForNullKey(V value) {  

6.         for (Entry<K,V> e = table[0]; e != null; e = e.next) {  

7.             if (e.key == null) {  

8.                 V oldValue = e.value;  

9.                 e.value = value;  

10.                e.recordAccess(this);  

11.                return oldValue;  

12.            }  

13.        }  

14.        modCount++;  

15.        addEntry(0, null, value, 0); // hash = 0, bucketIndex = 0  

16.        return null;  

17.    }  

注意,Hashtable和ConcurrentHashMap进行put时若value为null,将抛出NullPointerException。 

 

4. table默认初始大小 - 16

Java代码  

1. public HashMap(int initialCapacity, float loadFactor) {  

2.         // ...  

3.   

4.         this.loadFactor = loadFactor; // 0.75  

5.         threshold = initialCapacity; // 16  

6.         init(); // nothing  

7.     }  

8.   

9. public V put(K key, V value) {  

10.        if (table == EMPTY_TABLE) {  

11.            inflateTable(threshold);  

12.        }  

13.        // ...  

14.}  

15.  

16.private void inflateTable(int toSize) {  

17.        // Find a power of 2 >= toSize  

18.        int capacity = roundUpToPowerOf2(toSize); // 16  

19.  

20.        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);  

21.        table = new Entry[capacity];  

22.        initHashSeedAsNeeded(capacity);  

23.    }  

24.  

25.private static int roundUpToPowerOf2(int number) {  

26.        // assert number >= 0 : "number must be non-negative";  

27.        return number >= MAXIMUM_CAPACITY  

28.                ? MAXIMUM_CAPACITY  

29.                : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;  

30.    }  

 

5. 关于HashMap里的hash(Object key)方法

Java代码  

1. final int hash(Object k) {  

2.         int h = hashSeed;  

3.         if (0 != h && k instanceof String) {  

4.             return sun.misc.Hashing.stringHash32((String) k);  

5.         }  

6.   

7.         h ^= k.hashCode();  

8.   

9.         // This function ensures that hashCodes that differ only by  

10.        // constant multiples at each bit position have a bounded  

11.        // number of collisions (approximately 8 at default load factor).  

12.        h ^= (h >>> 20) ^ (h >>> 12);  

13.        return h ^ (h >>> 7) ^ (h >>> 4);  

14.    }  

15.  

16./** 

17.     * Initialize the hashing mask value. We defer initialization until we 

18.     * really need it. 

19.     */  

20.    final boolean initHashSeedAsNeeded(int capacity) {  

21.        boolean currentAltHashing = hashSeed != 0;  

22.        boolean useAltHashing = sun.misc.VM.isBooted() &&  

23.                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);  

24.        boolean switching = currentAltHashing ^ useAltHashing;  

25.        if (switching) {  

26.            hashSeed = useAltHashing  

27.                ? sun.misc.Hashing.randomHashSeed(this)  

28.                : 0;  

29.        }  

30.        return switching;  

31.    }  

 

有人用微信聊天,有人却在微信中学习,成长。下面是2016最HOT公众号,赶快试试新的关注方法吧!


关注方式
★长按二维码,选择“识别图中二维码”进行关注。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值