在java中高效的计数器
在编程中,经常会用到HashMap作为计数器,本文简单介绍三种实现方式
第一种,最直观的计数器。
public void naiveCounter(String sArr[]) {
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);
}
}
}
在这种方式中,每次循环都去检查Map中是否包含Key,如果包含则将原值+1再保存,如果不存在,则直接保存1.这种方式是最简单直接的一种方式,但是并不是最有效的方式,其低效的原因:
1、如果已经存在某个key(a),containsKey()和get()方法会扫描Map两次
2、由于Integer是不可变对象,因此每次循环,都会创建一个新的对象放到Map中。
第二种,比较好的计数器
由于上述原因,自然可以想到创建一个可变的Integer对象,这样可以避免创建过多的Integer对象,
可变的Integer对象定义如下:
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;
} public String toString() {
return Integer.toString(val);
}
}
然后将上面的计数器优化一下,改成下面这张格式
public void betterCounter(String[] sArr) {
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));
}
}
}
第三种,高效的计数器
上面第二种已经解决了创建过多Integer对象的问题,但是扫描两次Map,
其实在HashMap中,存在一个能够返回当前值的方法(HashMap.put(key,value)),
在上面的基础上,我们可以通过对原来的引用进行更新,而不必扫描两次Map
public void efficientCounter(String[] sArr) {
HashMap<String, MutableInteger> efficientCounter = new HashMap<String, MutableInteger>();
for (String a : sArr) {
MutableInteger initValue = new MutableInteger(1);
MutableInteger oldValue = efficientCounter.put(a, initValue);
//MutableInteger是可变的,此处只需判断之前是否为空,
// 如果非空,则更新MutableInteger的引用即可
if (oldValue != null) {
initValue.set(oldValue.get() + 1);
}
}
}
下面是经过500W次操作后,三者方法所消耗的时间
start test naiveCounter
end test naiveCounter,time is:5629
start test betterCounter
end test betterCounter,time is:5030
start test efficientCounter
end test efficientCounter,time is:4418
可以看出,最后一种确实是三种里面最高效的方式
在java中高效的计数器的更多相关文章
- 在 Java 中高效使用锁的技巧--转载
竞争锁是造成多线程应用程序性能瓶颈的主要原因 区分竞争锁和非竞争锁对性能的影响非常重要.如果一个锁自始至终只被一个线程使用,那么 JVM 有能力优化它带来的绝大部分损耗.如果一个锁被多个线程使用过,但 ...
- 七、如何在Java中高效检查一个数组是否含有一个值
如何检查一个数组(非排序的)是否包含特定的值.这是个非常有用或经常被在Java中使用.这是个在Stack Overflow中高得票的问题.在已经高得票的答案中,有许多不同的处理方法,但是时间的复杂度非 ...
- 161101、在Java中如何高效判断数组中是否包含某个元素
如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...
- 在Java中如何高效的判断数组中是否包含某个元素
原文出处: hollischuang(@Hollis_Chuang) 如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Ove ...
- 在Java中怎样高效的推断数组中是否包括某个元素
来自 http://www.hollischuang.com/archives/1269? 怎样检查一个数组(无序)是否包括一个特定的值?这是一个在Java中经经常使用到的并且非常实用的操作.同一时候 ...
- 在java中构建高效的结果缓存
文章目录 使用HashMap 使用ConcurrentHashMap FutureTask 在java中构建高效的结果缓存 缓存是现代应用服务器中非常常用的组件.除了第三方缓存以外,我们通常也需要在j ...
- 在Java中如何高效判断数组中是否包含某个元素
如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...
- Java中的GC操作及相关概念
一.GC Roots Tracing的基本思路:通过一系列名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所经过的路径称为引用链(Reference Chai ...
- 面试中关于Java中涉及到知识点(转)
本篇文章会对面试中常遇到的Java技术点进行全面深入的总结,帮助我们在面试中更加得心应手,不参加面试的同学也能够借此机会梳理一下自己的知识体系,进行查漏补缺. 1. Java中的原始数据类型都有哪些, ...
随机推荐
- 关于怎样拆毁Cuttheprice
最近我的chrome浏览器被一个叫cuttheprice的插件病毒感染了,总是弹出广告,真是让人抓狂,本来最近几天在复习算法,准备面试的,昨天忍了过去,今天实在受不了了,于是就干掉它吧.说干就干,刚开 ...
- centos7和windows7双系统安装
前些天安装了双系统(centos7+win7),其实网上关于这类的教程很多,这篇日志也只是针对本人安装过程中遇到的一些问题进行说明.我是按照先安装win7再安装centos7的顺序. 1.关于分区: ...
- vs2012+cmake+opencv+opencv unable to find a build program corresponding to "Visual Studio 12 Win64". CMAKE_MAKE_PROGRAM is not set
搜索了下,说什么的都有! 一,提示找不到 cmake-2.8.12.1 的 modles 卸载了cmake后发现 cmd 中的 cmake --version 还是 2.8.11.1 找到是我的cyg ...
- 汇编语言中,SP,BP ,SI,DI作用?
这个很简单: sp:表示栈顶指针,指向栈顶地址.与SS相配合使用.ss为栈段. bp:是基址指针,段地址默认在SS中.可以定位物理地址,比如:"mov ax,[bp+si+6]/mov ax ...
- SLF4J user manual
http://www.slf4j.org/manual.html The Simple Logging Facade for Java (SLF4J) serves as a simple facad ...
- 使用智遥工作流,优化SAP请购流程
传统请购流程,都是用户在SAP系统中填写请购单,然后再打印出来,递交给上级领导审批.领导审批完了,再到SAP系统中更新release标识.若中途请购单内容需要变更,则需要重新打印,审批. 智遥工作流, ...
- vi编辑器的三种模式
1.命令模式(command mode)—执行命令 在该模式中,可以输入命令来执行许多种功能.控制屏幕光标的移动,字符.字或行的删除,移动复制某区段及进入Insert mode下,或者到 last l ...
- Android 国际化图片资源文件
国际化 与字符串国际相似,在 res 下新建 drawable-zh 文件夹,存放中文环境下的图片 新建 drawable-en 作为英语环境下的图片 在 eclipse ...
- JSP个人总结
应用JSP技术开发动态网站 JSP基本语法 默认JSP: <%@ page language="java" contentType="text/html; char ...
- MVC——数据库增删改查(Razor)——Html语法
一.显示界面 .Models(模板) private MyDBDataContext _context = new MyDBDataContext(); public List<Info> ...