很多时候我们需要对一些高频出现的词汇或……做统计。使用一个map集合很容易就能做到这一点,那么怎样做才能做高效呢?举几个例子说明:
如:从数据库读取数据或从文本文件中读取数据,统计某些字符出现的次数
//统计str中one、two、three出现的次数
String str = "one two three two three three";
HashMap<String, Integer> counter1 = new HashMap<String, Integer>();
for (String a : sArr) {
if (counter1.containsKey(a)) {
int oldValue = counter1.get(a);
counter1.put(a, oldValue + 1);
} else {
counter1.put(a, 1);
}
}
上面的计数器是能满足要求的,但是它并不是最高效的,有两点原因:
1、Integer就像String一样是不可变的类型,计数每次增长都要重新创建一个Integer对象;
2、当统计次数大于一时,要使用containsKey(),get(),也就是说要从map集合中搜索两次;
从1入手改进下计数器,可以自定义一个类用来计数,如:
class customInt{
private int ct;
public customInt(int ct){
this.ct = ct;
}
public void setCt(int ct){
this.ct = ct;
}
public int getCt(){
return ct;
}
}
HashMap<String, customInt> counter2 = new HashMap<String, customInt>();
for (String a : sArr) {
if (counter2.containsKey(a)) {
customInt oldVal = counter2.get(a);
oldVal.setCt(oldVal.getCt() + 1);
} else {
counter2.put(a, new customInt(1));
}
}
//counter1和counter2 两次的输出(根据计算机以及搜索内容的不同输出结果肯定会有差异,但counter2耗时比counter1少):
结果很明显改进后的计数器明显比最初的高效,根据上面说到的两点对计数器效率的影响,再次对计数器进行改进优化。查API可知Map集合的put()方法,会返回与key相关联的旧值,没有则返回null(API:the previous value associated with key, or null if there was no mapping for key.)。对计数器再进行修改:
HashMap<String, customInt> counter3 = new HashMap<String, customInt>();
for (String a : sArr) {
customInt initInt = new customInt(1);
customInt oldVal = counter3.put(a, initInt);
if (oldVal != null) {
initInt.setCt(oldVal.getCt() + 1);
}
}
当然关于map集合作计数器的实现还有有很多其他的方式,例如:
HashMap<String, customInt> counter4 = new HashMap<String, customInt>();
for (String a : sArr) {
customInt val = counter4.get(a);
if (val != null) {
val.setCt(val.getCt() + 1);
} else {
counter4.put(a, new customInt(1));
}
}
//或者是使用int[]、AtomicInteger等来计数,都可以
HashMap<String, int[]> counter5 = new HashMap<String, int[]>();
for (String a : sArr) {
int[] val = counter5.get(a);
if (val != null) {
val[0]++;
} else {
counter5.put(a, new int[]{1});
}
}
HashMap<String, AtomicInteger> counter6 = new HashMap<String, AtomicInteger>();
for (String a : sArr) {
AtomicInteger val = counter6.get(a);
if (val != null) {
val.incrementAndGet();
} else {
counter6.put(a, new AtomicInteger(1));
}
}
以上是使用map集合实现几种计数器,究竟哪种效率最高,可能会因搜索数据量,统计事物出现的频率,计算机等因素有所不同,根据我个人的实验,使用int[ ](counter5)最为高效。
有兴趣的可以自己测验试试。记得砖块捡小的拍哦……