最有效的方法来增加在Map中的值

来源:互联网 发布:淘宝助理要收费 吗 编辑:程序博客网 时间:2024/06/05 22:40

关于这个是在一个博客上看到的,就像试一下,测试结果出人意料。

看到这个标题可能还是觉得有点抽象,那么首先来一段代码:

int count = map.containsKey(string) ? map.get(string) : 0;map.put(string, count + 1);

其中contains(),get() and put()方法都要在map中根据key查找,需要朝找三次,那么在优化过后只需要查找一次。

以上这段代码以及稍后的优化思路来自:http://blog.pengyifan.com/most-efficient-way-to-increment-a-map-value-in-java-only-search-the-key-once/

这是干什么用的,那么在直接看下面的一个应用就很清楚了,代码如下:

/**     * 给你一组字符串 如 {5,2,3,2,4,5,1,2,1,5},让你输出里面出现次数最多且数值最大的一个,出现几次      * 优点:时间复杂度为O(n)     * 缺点:暂时没发现     */     public static void method2(){            int[] datas = {5,2,3,2,4,5,1,2,1,5};      Map<Integer,Integer> map = new HashMap<Integer, Integer>();      for (int i = 0; i < datas.length; i++) {          Integer key = datas[i];          Integer value = map.get(key);  //****//        if(value != null){              map.put(key, ++value);  //****//        }else{              map.put(key, 1);          }      }            int maxTime = 0;      int maxTime_num = 0;      Set<Integer> keySet = map.keySet();      Iterator<Integer> it = keySet.iterator();      while(it.hasNext()){          Integer key = it.next();          Integer value = map.get(key);          System.out.println(key+":"+value);                    if(value >= maxTime){              maxTime = value;              if(key > maxTime_num){                  maxTime_num = key;              }          }      }      System.out.println("出现次数最多:"+maxTime+"次;且最大的数是:"+maxTime_num);           }  
这段代码是以前写的:http://blog.csdn.net/wufengui1315/article/details/39226103

关于这个算法题还写了一种基于数组的实现,当然这不是本篇文章的重点,有兴趣可以看下。

然后我写了一个测试用例:

public static void main(String[] args) throws UnsupportedEncodingException {//System.out.println(addWithoutArithmetic(2,15));//System.out.println(addWithoutArithmetic(5,17));int length = 10000000*2; int[] datas = new int[length];   for (int i = 0; i < datas.length; i++) { datas[i] = (int) (Math.random()*(length/2));}method2(datas);method3(datas);method4(datas);}
其中method2,method3,method4与上面的基本一样,不同的部分按顺序如下:

Map<Integer,MutableInteger> map = new HashMap<Integer, MutableInteger>();    for (int i = 0; i < datas.length; i++) {          Integer key = datas[i];          MutableInteger count = map.get(key);        if (count != null) {          count.set(count.get() + 1);        } else {          map.put(key, new MutableInteger(1));        }            }  

Map<Integer,Integer> map = new HashMap<Integer, Integer>();      for (int i = 0; i < datas.length; i++) {          Integer key = datas[i];          Integer value = map.get(key);          if(value != null){              map.put(key, ++value);          }else{              map.put(key, 1);          }      }  

Map<Integer,Integer> map = new HashMap<Integer, Integer>();      for (int i = 0; i < datas.length; i++) {          Integer key = datas[i];          Integer value = map.containsKey(key)? map.get(key):1;          map.put(key, value+1);      }  

打印结果:

出现次数最多:13次;且最大的数是:4814069
time:12614
出现次数最多:13次;且最大的数是:4814069
time:8662
出现次数最多:14次;且最大的数是:4814069
time:8287

-------------------------------------

结果与原博客所说的相差很远,本来说效率最高的花的时间最多,效率最差的却花的时间最少。

尴尬

经过多次测试,结果很稳定,与上面类似,

那么,为什么会这样?

map中的查找并不是顺序查找,而是根据哈希值查找,查找速度很快。我只能这样理解。


写到这里,想起之前的有个是基于数组的写法(O(n)),就是method1(),然后重新跑了几遍,结果如下:

method1()在这里有写:http://blog.csdn.net/wufengui1315/article/details/39226103

出现次数最多:13次;且最大的数是:9972122
time:17053
出现次数最多:13次;且最大的数是:9972122
time:10130
出现次数最多:14次;且最大的数是:9972122
time:9166
最多的出现13次
出现次数最多:13次;且最大的数是:9972122    //(method1())
time:569

结果还是基于数组的最快,看数据很清楚了。




0 0