关于这个是在一个博客上看到的,就像试一下,测试结果出人意料。
看到这个标题可能还是觉得有点抽象,那么首先来一段代码:
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
结果还是基于数组的最快,看数据很清楚了。