Map 的计数功能

最近看 << Thinking in Java >>,发现Map 有一个很好地作用:计数!

举个例子:设Pet 有5个种类,包括 dog, cat, rat, mouse, pig。 List 集合随机添加不同的宠物,比如添加了100只,怎么统计这100 只宠物中,dog 有几只,cat 有几只...


实现代码:

public class PetCount {

static class PetCounter extends HashMap<String, Interger> {
public void count(String type) {
Integer quantity = get(type);
if (quantity == null)
put(type, 1);
else 
put(type, quantity+1);
}
}


public static void countPets(PetCreator creator) {
PetCounter counter = new PetCounter();
for (Pet pet: creator.createArray(20)) {
if ((pet instanceof Dog)
counter.count("Dog");
if ((pet instanceof Cat)
counter.count("Cat");
if ((pet instanceof Rat)
counter.count("Rat");
if ((pet instanceof Mouse)
counter.count("Mouse");
if ((pet instanceof Pig)
counter.count("Pig");
}
}
}


===================================================================================================================================


以下是参考网友转发的:


这本是多年前一个stackoverflow上的一个讨论,回答中涉及到了多种计数方法。对于一个key-value结构的map,我们在编程时会经常涉及到key是对象,而value是一个integer或long来负责计数,从而统计多个key的频率。 
  
面对这样一个基本需求,可能有很多种实现。比如最基本的使用jdk的map直接实现——value是一个integer或者long。其基本代码型如下: 
  
   1: final Map<String, Integer> freq = new HashMap<String, Integer>(); 
   2: int count = ntainsKey(word) ? freq.get(word) : 0; 
   3: freq.put(word, count + 1); 
逻辑简单,判断是否存在,是则get取值,否则为0,再put进去一个加1后的值。总共要contain判断,get,put做三次方法调用。 
  
当然进一步我们可以把contain判断去掉,代码如下: 
  
   1: final Map<String, Integer> freq = new HashMap<String, Integer>(); 
   2: Integer count = freq.get(word); 
   3: if (count == null) { 
   4:     freq.put(word, 1); 
   5: } else { 
   6:     freq.put(word, count + 1); 
   7: } 
一般情况,我们做到这个地步,多数人对其逻辑已经满足,简单性能也能接受,试着想一下,难道不是这样吗?get加put,解决了。 
  
当然这样的实现还不够高效,于是我们开始去尝试实现或寻找更高效的方法,看看开源的集合类库是否有需要的: 
  
有个Trove,可以让我们参考一下: 
  
   1: final TObjectIntHashMap<String> freq = new TObjectIntHashMap<String>(); 
   2: freq.adjustOrPutValue(word, 1, 1); 
这样做,非常优雅啊,性能如何呢?不知道,需要看源码了解细节。那再看看大名鼎鼎的guava如何呢? 
  
   1: AtomicLongMap<String> map = AtomicLongMap.create(); 
   2: map.getAndIncrement(word); 
实现依然优雅,但是,但是看这名字,再看源码,好吧,线程安全的,支持并发,这不好搞了,我们场景需要吗?不需要的话直觉告诉我们这肯定是“慢”的。再找: 
  
   1: Multiset<String> bag = HashMultiset.create(); 
   2: bag.add(word); 


这个看上去合适了,bag的实现明显好很多,而且从语义理解上,这样的接口更容易让人理解。 
那么这些方法,性能如何呢?
一般结论:单线程使用MutableInt,多线程使用guava的AtomicLongMap。 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值