在编程中,经常会用到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中高效的计数器的更多相关文章

  1. 在 Java 中高效使用锁的技巧--转载

    竞争锁是造成多线程应用程序性能瓶颈的主要原因 区分竞争锁和非竞争锁对性能的影响非常重要.如果一个锁自始至终只被一个线程使用,那么 JVM 有能力优化它带来的绝大部分损耗.如果一个锁被多个线程使用过,但 ...

  2. 七、如何在Java中高效检查一个数组是否含有一个值

    如何检查一个数组(非排序的)是否包含特定的值.这是个非常有用或经常被在Java中使用.这是个在Stack Overflow中高得票的问题.在已经高得票的答案中,有许多不同的处理方法,但是时间的复杂度非 ...

  3. 161101、在Java中如何高效判断数组中是否包含某个元素

    如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...

  4. 在Java中如何高效的判断数组中是否包含某个元素

    原文出处: hollischuang(@Hollis_Chuang) 如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Ove ...

  5. 在Java中怎样高效的推断数组中是否包括某个元素

    来自 http://www.hollischuang.com/archives/1269? 怎样检查一个数组(无序)是否包括一个特定的值?这是一个在Java中经经常使用到的并且非常实用的操作.同一时候 ...

  6. 在java中构建高效的结果缓存

    文章目录 使用HashMap 使用ConcurrentHashMap FutureTask 在java中构建高效的结果缓存 缓存是现代应用服务器中非常常用的组件.除了第三方缓存以外,我们通常也需要在j ...

  7. 在Java中如何高效判断数组中是否包含某个元素

    如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...

  8. Java中的GC操作及相关概念

    一.GC Roots Tracing的基本思路:通过一系列名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所经过的路径称为引用链(Reference Chai ...

  9. 面试中关于Java中涉及到知识点(转)

    本篇文章会对面试中常遇到的Java技术点进行全面深入的总结,帮助我们在面试中更加得心应手,不参加面试的同学也能够借此机会梳理一下自己的知识体系,进行查漏补缺. 1. Java中的原始数据类型都有哪些, ...

随机推荐

  1. oracle----复制表中的数据

    两种方法: 1. 在创建表的时候将数据从其他表中复制过来(并且表的结构也复制过来): 语法: CREATE TABLE table_name AS SELECT column1,......|* FR ...

  2. IIS的Unicode漏洞攻击

    IIS有十多种常见漏洞,但利用得最多的莫过于Unicode解析错误漏洞.微软IIS 4.0/5.0在Unicode字符解码的实现中存在一个安全漏洞,用户可以远程通过IIS执行任意命令.当IIS打开文件 ...

  3. MySQL注入中load_file()函数的应用

    常用的一些Load_File()函数攻击手法:

  4. 《php和mysql web开发》读书笔记

    总算是强迫自己把第一篇给看完了,在这里做一个小结,将一些知识点记录下来. 一.第一篇 使用PHP 1.php中的注释.php支持c.c++和shell脚本风格注释 /**/多行注释  //单行注释   ...

  5. (重)POJ 3020Antenna Placement

    http://poj.org/problem?id=3020 呃...这个题不是很会,所以找了大神的博客做了参考,说得很详细 http://blog.csdn.net/lyy289065406/art ...

  6. html5 高级动画精灵

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  7. Linux kernel ‘aac_send_raw_srb’函数输入验证漏洞

    漏洞名称: Linux kernel ‘aac_send_raw_srb’函数输入验证漏洞 CNNVD编号: CNNVD-201311-422 发布时间: 2013-11-29 更新时间: 2013- ...

  8. 对 Azure Backup 的常见配置问题进行故障排除

    Giridhar Mosay云 + Enterprise 项目经理 这篇博客文章有助于解决 Microsoft云备份解决方案(即 Azure Backup)的常见配置问题.客户通常会在安装或注册 ...

  9. 处理MVC中默认的Json方法返回时间的问题

    利用 Json方法返回 数据时,如果有时间格式,会变成 "\/Date(1369419656217)\/" 这个样子,问了同事找到个解决方法 using Newtonsoft.Js ...

  10. acm位运算应用 搜索

    acm位运算应用 搜索 搜索    此处不讲题目,只讲位运算是怎样在这些题中实现和应用的.由于搜索题往往是基于对状态的操作,位运算往往特别有效,优化之后的效果可以有目共睹.    例1.POJ 132 ...