问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何高效的实现一个计数器map

发布网友 发布时间:2022-05-02 00:53

我来回答

1个回答

热心网友 时间:2022-04-22 09:32

这本是多年前一个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 = freq.containsKey(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的实现明显好很多,而且从语义理解上,这样的接口更容易让人理解。

那么这些方法,性能如何呢?做了个简单的比较,将26个英文字母做key,均匀循环若干次比较各个方法的效率(单纯时间效率),而且时间不统计构建开销。外加了一个线程安全版的concurrentMap实现,而其实google的guava里的AtomicLongMap也是包装了juc的concurrentMap而已。里面有最终极的MutableInt方法,找找看吧,性能最好的就是它了。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
硅胶与液态硅胶手机壳的区别 什么样的过敏会传染 过敏的原理是什么?为什么有的人过敏,有的人不过敏?谢谢! 过敏为什么会痒 评审报告需要注意什么 财政评审流程及注意事项 高效项目评审的6大注意事项 银行双录 什么意思 什么是银行双录 在异地哪些可公证 吃烤肉喝什么能刮油 设计一个计数器,其计数次数为10万次并画出梯形图? 一个计数器上有7颗,各位和十位相差2颗,这个数是多少? 有经验的人帮帮忙 减肥期间 如果吃了烤肉 烧烤 如何补救 听说酸奶可以 是吗? 一个计数器的最右边一位是个位。如果在这个计数器的右起第七位上拨七颗算珠表示的数是( ) 吃大餐时冲一杯大麦茶真的能刮油吗? 一个计数器定4小时响一次,现在11点,已经响了13次,第一次是什么时间,这是怎么算呢? 吃烧烤后吃什么可以帮助减肥? 在一个计数器的个位和十位上共放9颗珠子,所表示最小的两位数是多少? 吃了烤肉感觉很腻,吃什么食物就可以解腻? 吃完烧烤以后,该怎样才能解油腻 ? 烤肉吃完吃什么解油腻 给情人的春节一封信 写给婚外情人的情书 给婚外情人的一封信 为什么说Dr.ERWIN的寡肽精华可以用来保湿皮肤? Dr.ERWIN的寡肽原液上脸是一种什么肤感啊? 寡肽原液白天用还是晚上用? 婵皙面霜含生长因子寡肽成分? 科颜氏果冻清爽高保湿面霜可以和寡肽原液一起使用吗 吃完烤肉吃什么不会发胖 你好,如何用一个计数器和一个时间继电器控制气缸的动作次数 自己定义一个计数器,比如说count什么的.每次执行该语句自增一,怎么写程序,Java 山东的电信在农村楼上没4g信号楼下无2g,楼下4g正常除乡镇住地外信号4g差特别2g有的地方没信号? 给老师的感恩信 实验室里有一个计数器,一圈一共24个格,按照顺时针顺序标了0~23这24个数.每经过8分钟,指针就会顺时针方 中国电信的数据流量信号差怎么解决好 用Verilog编一个计数器的程序 高分求助:我用的是山东电信的3G无线网卡,网速白天晚上一直都很慢。 我本人在昆明。什么原因,求解决的方 感恩老师的信 怎么用手机往别人的QQ邮箱里发信息啊! 求一篇,致老师的信900字作文,急!急!!! 怎么画开运桃花眼妆? 强攻弱受是什么意思? 怎么用笔记本电脑采用多种方式截屏,具体怎么操作? 我在知道里面看到你回答别人的提问,觉得你推荐的强攻弱受的文都蛮好看的那,可不可以再推荐一些那? 写给老师的感恩信 你们都是如何画出可爱的桃花眼妆的? 给感恩老师的信,求快点 我是中国电信手机卡,为什么最近信号不好?