深入分析IntHashMap

 一、IntHashMap

   1.1 准备

  先从官网下载jar包:javasoft-collection.jar,解压后将jar包build到Java项目中.

  1.2 IntHashMap类图

  1.3 IntHashMap流程图

  

   从上面类图可以看出IntHashMap和HashMap一样都是基于Map接口,在Map中最常用的2个方法是put()和get()方法。大家都知道Map是从键到值的映射,每个键不能出现重复且每个键最多只能映射到一个值。那么IntHashMap是如何保证键的唯一性?可能大家会想IntHashMap的键是int类型,使用==来比较,这样子虽然能保证键的唯一。但是随着元素的增加,每次都进行比较效率会越来越低。什么样的数据结构能快速的存储元素?答案是数组。HashMap中是通过hash计算出bucketIndex位置找到数组中对应的元素,那么IntHashMap呢?IntHashMap亦如此,唯一不同的是计算bucketIndex的算法通过indexFor()方法拿到bucketindex后。它会先去数组中找这个位置上的元素IntEntry<V>是否存在,如果存在的话,再通过key去查找value,然后将新值替换掉旧value。
代码清单2如下:

[java]  view plain  copy
  1. /** 
  2.    * Returns index for key 
  3.    */  
  4.   protected int indexFor(int key, int length) {  
  5. key += ~(key << 9);  
  6. key ^=  (key >>> 14);  
  7. key +=  (key << 4);  
  8. key ^=  (key >>> 10);  
  9. return key & (length-1);  
  10.   }  
  代码清单3如下:

[java]  view plain  copy
  1. int i = indexFor(key, table.length);  
  2.   
  3. for (IntEntry<V> e = table[i]; e != null; e = e.next) {  
  4.        if (e.key == key) {  
  5.              V oldValue = e.value;  
  6.              e.value = value;  
  7.              e.recordAccess(this);  
  8.              return oldValue;  
  9.         }  
  10. }  

 二、IntHashMap与HashMap比较

   2.1 运行效率比较

  创建一个测试类,分别往IntHashMap和HashMap各插入1万和5万条数据来测试它们性能、GC和内存使用

[java]  view plain  copy
  1. package com.lll.operator;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5.   
  6. import ch.javasoft.util.intcoll.IntHashMap;  
  7.   
  8. public class ShiftTest {  
  9.   
  10.     //  IntHashMap<String> map = new IntHashMap<String>();  
  11.     HashMap<Integer,String> map = new HashMap<Integer,String>();  
  12.   
  13.     public void add()  
  14.     {  
  15.         for (int i = 0; i < 10000;i++) {  
  16.             for(int j = 0;j<50000;j++)  
  17.             {  
  18.                 if(map.get(j) == null)  
  19.                 {  
  20.                     map.put(j, "小毛驴");  
  21.                 }  
  22.             }  
  23.         }  
  24.     }  
  25.     public static void main(String[] args) {  
  26.         long curTime = System.currentTimeMillis();  
  27.         ShiftTest shiftTest = new ShiftTest();  
  28.         shiftTest.add();  
  29.         long curTime2 = System.currentTimeMillis();  
  30.         System.out.println("耗时:"+(curTime2-curTime)+"ms");  
  31.         try {  
  32.             Thread.sleep(5000);  
  33.         } catch (InterruptedException e) {  
  34.             // TODO Auto-generated catch block  
  35.             e.printStackTrace();  
  36.         }  
  37.     }  
  38.   
  39. }  

   2.2 Visual GC比较

  HashMap:

  IntHashMap:

   2.3 结果分析

10000条数据测 试结果:
Map类型 第一次取样 第二次取样 第三次取样 GC
IntHashMap 795ms 815ms 807ms NO GC
HashMap 866ms 927ms 861ms 11.978ms

  50000条数据测 试结果:
Map类型 第一次取样 第二次取样 第三次取样 GC时间
IntHashMap 5166ms 4817ms 4997ms NO GC
HashMap 4388ms 4430ms 3876ms 40.453ms

    从上面的测试结果可以看出,HashMap会随着容器大小的变化效率明显变慢。也许从数据测试结果来看使用IntHashMap在性能上比HashMap并没有太大优势甚至效率还要低些,但是从GC上来看明显IntHashMap更有优势。那么是什么让他们产生这样的差异?

   2.4 差异一

  HashMap在插入元素过程中会在堆中产生大量的Integer实例(如下图-Profiler界面),参考代码清单4。而IntHashMap不一样,它是以int作为key值类型(见代码清单5),能够减少Integer实例的产生,减少GC负担。

  Profiler界面


代码清单4:

[java]  view plain  copy
  1. static class Entry<K,V> implements Map.Entry<K,V> {  
  2.        final K key;  
  3.        V value;  
  4.        Entry<K,V> next;  
  5.        int hash;  
  6.   
  7.        /** 
  8.         * Creates new entry. 
  9.         */  
  10.        Entry(int h, K k, V v, Entry<K,V> n) {  
  11.            value = v;  
  12.            next = n;  
  13.            key = k;  
  14.            hash = h;  
  15.        }  

代码清单5:

[java]  view plain  copy
  1. public static class IntEntry<VV> implements IntMap.IntEntry<VV> {  
  2.         protected final int key;  
  3.         protected VV value;  
  4.         protected IntEntry<VV> next;  
  5.   
  6.         /** 
  7.          * Create new entry. 
  8.          */  
  9.         protected IntEntry(int k, VV v, IntEntry<VV> n) {  
  10.             value = v;  
  11.             next = n;  
  12.             key = k;  
  13.         }  

   2.5 差异二

 在遍历时,IntHashMap(代码清单6)没有对hash进行比较。

 代码清单6

[java]  view plain  copy
  1. public V get(int key) {  
  2.         int i = indexFor(key, table.length);  
  3.         IntEntry<V> e = table[i];   
  4.         while (true) {  
  5.             if (e == null)  
  6.                 return null;  
  7.             if (e.key == key)   
  8.                 return e.value;  
  9.             e = e.next;  
  10.         }  
  11.     }  
 HashMap遍历代码清单7
[java]  view plain  copy
  1. final Entry<K,V> getEntry(Object key) {  
  2.         int hash = (key == null) ? 0 : hash(key);  
  3.         for (Entry<K,V> e = table[indexFor(hash, table.length)];  
  4.              e != null;  
  5.              e = e.next) {  
  6.             Object k;  
  7.             if (e.hash == hash &&  
  8.                 ((k = e.key) == key || (key != null && key.equals(k))))  
  9.                 return e;  
  10.         }  
  11.         return null;  
  12.     }  



作者: 小毛驴,一个游戏人 
梦想:世界和平   
原文地址: http://blog.csdn.net/liulongling
文章如有错误之处,还请见谅并能给予指正!     
本博客中未标明转载的文章归作者 小毛驴所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
commons-lang3.3.1.jar、Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。为JRE5.0+的更好的版本所提供 Jar文件包含的类: META-INF/MANIFEST.MFMETA-INF/LICENSE.txtMETA-INF/NOTICE.txtorg.apache.commons.lang.ArrayUtils.class org.apache.commons.lang.BitField.class org.apache.commons.lang.BooleanUtils.class org.apache.commons.lang.CharEncoding.class org.apache.commons.lang.CharRange.class org.apache.commons.lang.CharSet.class org.apache.commons.lang.CharSetUtils.class org.apache.commons.lang.CharUtils.class org.apache.commons.lang.Clas sUtils.class org.apache.commons.lang.Entities$ArrayEntityMap.class org.apache.commons.lang.Entities$BinaryEntityMap.class org.apache.commons.lang.Entities$EntityMap.class org.apache.commons.lang.Entities$HashEntityMap.class org.apache.commons.lang.Entities$LookupEntityMap.class org.apache.commons.lang.Entities$MapIntMap.class org.apache.commons.lang.Entities$PrimitiveEntityMap.class org.apache.commons.lang.Entities$TreeEntityMap.class org.apache.commons.lang.Entities.class org.apache.commons.lang.IllegalClassException.class org.apache.commons.lang.IncompleteArgumentException.class org.apache.commons.lang.IntHashMap$Entry.class org.apache.commons.lang.IntHashMap.class org.apache.commons.lang.LocaleUtils.class org.apache.commons.lang.NotImplementedException.class org.apache.commons.lang.NullArgumentException.class org.apache.commons.lang.NumberRange.class org.apache.commons.lang.NumberUtils.class org.apache.commons.lang.ObjectUtils$Null.class org.apache.commons.lang.ObjectUtils.class org.apache.commons.lang.RandomStringUtils.class org.apache.commons.lang.SerializationException.class org.apache.commons.lang.SerializationUtils.class org.apache.commons.lang.StringEscapeUtils.class org.apache.commons.lang.StringUtils.class org.apache.commons.lang.SystemUtils.class org.apache.commons.lang.UnhandledException.class org.apache.commons.lang.Validate.class org.apache.commons.lang.WordUtils.class org.apache.commons.lang.builder.CompareToBuilder.class org.apache.commons.lang.builder.EqualsBuilder.class org.apache.commons.lang.builder.HashCodeBuilder.class org.apache.commons.lang.builder.ReflectionToStringBuilder$1.class org.apache.commons.lang.builder.ReflectionToStringBuilder.class org.apache.commons.lang.builder.StandardToStringStyle.class org.apache.commons.lang.builder.ToStringBuilder.class org.apache.commons.lang.builder.ToStringStyle$DefaultToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$MultiLineToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$NoFieldNameToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$ShortPrefixToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$SimpleToStringStyle.class org.apache.commons.lang.builder.ToStringStyle.class org.apache.commons.lang.enum.Enum$Entry.class org.apache.commons.lang.enum.Enum.class org.apache.commons.lang.enum.EnumUtils.class org.apache.commons.lang.enum.ValuedEnum.class org.apache.commons.lang.enums.Enum$Entry.class org.apache.commons.lang.enums.Enum.class org.apache.commons.lang.enums.EnumUtils.class org.apache.commons.lang.enums.ValuedEnum.class org.apache.commons.lang.exception.ExceptionUtils.class org.apache.commons.lang.exception.Nestable.class org.apache.commons.lang.exception.NestableDelegate.class org.apache.commons.lang.exception.NestableError.class org.apache.commons.lang.exception.NestableException.class org.apache.commons.lang.exception.NestableRuntimeException.class org.apache.commons.lang.math.DoubleRange.class org.apache.commons.lang.math.FloatRange.class org.apache.commons.lang.math.Fraction.class org.apache.commons.lang.math.IntRange.class org.apache.commons.lang.math.JVMRandom.class org.apache.commons.lang.math.LongRange.class org.apache.commons.lang.math.NumberRange.class org.apache.commons.lang.math.NumberUtils.class org.apache.commons.lang.math.RandomUtils.class org.apache.commons.lang.math.Range.class org.apache.commons.lang.mutable.Mutable.class org.apache.commons.lang.mutable.MutableBoolean.class org.apache.commons.lang.mutable.MutableByte.class org.apache.commons.lang.mutable.MutableDouble.class org.apache.commons.lang.mutable.MutableFloat.class org.apache.commons.lang.mutable.MutableInt.class org.apache.commons.lang.mutable.MutableLong.class org.apache.commons.lang.mutable.MutableObject.class org.apache.commons.lang.mutable.MutableShort.class org.apache.commons.lang.text.CompositeFormat.class org.apache.commons.lang.text.StrBuilder$StrBuilderReader.class org.apache.commons.lang.text.StrBuilder$StrBuilderTokenizer.class org.apache.commons.lang.text.StrBuilder$StrBuilderWriter.class org.apache.commons.lang.text.StrBuilder.class org.apache.commons.lang.text.StrLookup$MapStrLookup.class org.apache.commons.lang.text.StrLookup.class org.apache.commons.lang.text.StrMatcher$CharMatcher.class org.apache.commons.lang.text.StrMatcher$CharSetMatcher.class org.apache.commons.lang.text.StrMatcher$NoMatcher.class org.apache.commons.lang.text.StrMatcher$StringMatcher.class org.apache.commons.lang.text.StrMatcher$TrimMatcher.class org.apache.commons.lang.text.StrMatcher.class org.apache.commons.lang.text.StrSubstitutor.class org.apache.commons.lang.text.StrTokenizer.class org.apache.commons.lang.time.DateFormatUtils.class org.apache.commons.lang.time.DateUtils$DateIterator.class org.apache.commons.lang.time.DateUtils.class org.apache.commons.lang.time.DurationFormatUtils$Token.class org.apache.commons.lang.time.DurationFormatUtils.class org.apache.commons.lang.time.FastDateFormat$CharacterLiteral.class org.apache.commons.lang.time.FastDateFormat$NumberRule.class org.apache.commons.lang.time.FastDateFormat$PaddedNumberField.class org.apache.commons.lang.time.FastDateFormat$Pair.class org.apache.commons.lang.time.FastDateFormat$Rule.class org.apache.commons.lang.time.FastDateFormat$StringLiteral.class org.apache.commons.lang.time.FastDateFormat$TextField.class org.apache.commons.lang.time.FastDateFormat$TimeZoneDisplayKey.class org.apache.commons.lang.time.FastDateFormat$TimeZoneNameRule.class org.apache.commons.lang.time.FastDateFormat$TimeZoneNumberRule.class org.apache.commons.lang.time.FastDateFormat$TwelveHourField.class org.apache.commons.lang.time.FastDateFormat$TwentyFourHourField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitMonthField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitNumberField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitYearField.class org.apache.commons.lang.time.FastDateFormat$UnpaddedMonthField.class org.apache.commons.lang.time.FastDateFormat$UnpaddedNumberField.class org.apache.commons.lang.time.FastDateFormat.class org.apache.commons.lang.time.StopWatch.class

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值