黑马程序员_java高效计数器

------- android培训java培训、期待与您交流! ----------

你可能经常使用HashMap作为一个计数器来理解频率的东西从数据库或文本。本文比较了3种不同的方法来实现计数器使用HashMap。

1、传统的计数器

如果你使用这样一个计数器,你的代码可能看起来像下面的:

String s = "one two three two three three";
String[] sArr = s.split(" ");
 
//naive approach    
HashMap<String, Integer> counter = new HashMap<String, Integer>();
 
for (String a : sArr) {
    if (counter.containsKey(a)) {
        int oldValue = counter.get(a);
        counter.put(a, oldValue + 1);
    } else {
        counter.put(a, 1);
    }
}

在每个循环,你检查是否存在与否的关键。如果是,增加旧值1,如果不是,将它设置为1。该方法简单、直观,但它不是最有效的方法。这种方法被认为是低效率的原因如下:

>>containsKey(),get()被称为两次当一个键已经存在。这意味着搜索地图两次。

>>因为整数是不可变的,每个循环将创建一个新的一个增量的旧值

2、更好的计数器

我们想要一个可变的整数自然避免创建许多整数对象。一个可变的整数类定义如下:

这似乎是更好的,因为它不需要创建许多整数对象了。然而,搜索仍是两次在每个循环如果一个关键的存在。

class MutableInteger {
 
    private int val;
 
    public MutableInteger(int val) {
        this.val = val;
    }
 
    public int get() {
        return val;
    }
 
    public void set(int val) {
        this.val = val;
    }
 
    //used to print value convinently
    public String toString(){
        return Integer.toString(val);
    }
}

和计数器是改善和改变如下:

HashMap<String, MutableInteger> newCounter = new HashMap<String, MutableInteger>();    
 
for (String a : sArr) {
    if (newCounter.containsKey(a)) {
        MutableInteger oldValue = newCounter.get(a);
        oldValue.set(oldValue.get() + 1);
    } else {
        newCounter.put(a, new MutableInteger(1));
    }
}

3、高效的计数器

这个HashMap。把(key,value)方法返回当前的价值的关键。这是有用的,因为我们可以使用参考旧的值来更新值没有搜索一个更多的时间!

HashMap<String, MutableInteger> efficientCounter = new HashMap<String, MutableInteger>();
 
for (String a : sArr) {
    MutableInteger initValue = new MutableInteger(1);
    MutableInteger oldValue = efficientCounter.put(a, initValue);
 
    if(oldValue != null){
        initValue.set(oldValue.get() + 1);
    }
}

4、性能差异

测试性能的三种不同的方法,使用以下代码。性能测试是在100万次。原始的结果如下:

Naive Approach : 222796000
Better Approach: 117283000
Efficient Approach: 96374000

不同的是重要的- 223与117和96。有很多区别,比较幼稚,这表明创建对象是昂贵的!

String s = "one two three two three three";
String[] sArr = s.split(" ");
 
long startTime = 0;
long endTime = 0;
long duration = 0;
 
// naive approach
startTime = System.nanoTime();
HashMap<String, Integer> counter = new HashMap<String, Integer>();
 
for (int i = 0; i < 1000000; i++)
    for (String a : sArr) {
        if (counter.containsKey(a)) {
            int oldValue = counter.get(a);
            counter.put(a, oldValue + 1);
        } else {
            counter.put(a, 1);
        }
    }
 
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("Naive Approach :  " + duration);
 
// better approach
startTime = System.nanoTime();
HashMap<String, MutableInteger> newCounter = new HashMap<String, MutableInteger>();
 
for (int i = 0; i < 1000000; i++)
    for (String a : sArr) {
        if (newCounter.containsKey(a)) {
            MutableInteger oldValue = newCounter.get(a);
            oldValue.set(oldValue.get() + 1);
        } else {
            newCounter.put(a, new MutableInteger(1));
        }
    }
 
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("Better Approach:  " + duration);
 
// efficient approach
startTime = System.nanoTime();
 
HashMap<String, MutableInteger> efficientCounter = new HashMap<String, MutableInteger>();
 
for (int i = 0; i < 1000000; i++)
    for (String a : sArr) {
        MutableInteger initValue = new MutableInteger(1);
        MutableInteger oldValue = efficientCounter.put(a, initValue);
 
        if (oldValue != null) {
            initValue.set(oldValue.get() + 1);
        }
    }
 
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("Efficient Approach:  " + duration);

当你使用一个计数器,你可能还需要一个函数来进行地图的价值。你可以查看常用方法的HashMap。

------- android培训java培训、期待与您交流! ----------

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值