文档章节

Java 使用Map作计数器

有如此
 有如此
发布于 2014/10/31 21:32
字数 714
阅读 206
收藏 1

   很多时候我们需要对一些高频出现的词汇或……做统计。使用一个map集合很容易就能做到这一点,那么怎样做才能做高效呢?举几个例子说明:

如:从数据库读取数据或从文本文件中读取数据,统计某些字符出现的次数

//统计str中one、two、three出现的次数
String str = "one two three two three three";

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

上面的计数器是能满足要求的,但是它并不是最高效的,有两点原因:

1、Integer就像String一样是不可变的类型,计数每次增长都要重新创建一个Integer对象;

2、当统计次数大于一时,要使用containsKey(),get(),也就是说要从map集合中搜索两次;

    从1入手改进下计数器,可以自定义一个类用来计数,如:

class customInt{
    private int ct;
    public customInt(int ct){
        this.ct = ct;
    }
    
    public void setCt(int ct){
        this.ct = ct;
    }
    
    public int getCt(){
        return ct;
    }
}

HashMap<String, customInt> counter2 = new HashMap<String, customInt>();		
for (String a : sArr) {
    if (counter2.containsKey(a)) {
        customInt oldVal = counter2.get(a);
        oldVal.setCt(oldVal.getCt() + 1);
    } else {
        counter2.put(a, new customInt(1));
    }
}

//counter1和counter2 两次的输出(根据计算机以及搜索内容的不同输出结果肯定会有差异,但counter2耗时比counter1少):

结果很明显改进后的计数器明显比最初的高效,根据上面说到的两点对计数器效率的影响,再次对计数器进行改进优化。查API可知Map集合的put()方法,会返回与key相关联的旧值,没有则返回null(API:the previous value associated with key, or null if there was no mapping for key.)。对计数器再进行修改:

HashMap<String, customInt> counter3 = new HashMap<String, customInt>();		
for (String a : sArr) {
    customInt initInt = new customInt(1);
    customInt oldVal = counter3.put(a, initInt);
    if (oldVal != null) {
       initInt.setCt(oldVal.getCt() + 1);
    }
}

    当然关于map集合作计数器的实现还有有很多其他的方式,例如:

HashMap<String, customInt> counter4 = new HashMap<String, customInt>();		
for (String a : sArr) {
    customInt val = counter4.get(a); 		
    if (val != null) {
	val.setCt(val.getCt() + 1);
    } else {
	counter4.put(a, new customInt(1));
    }
}
//或者是使用int[]、AtomicInteger等来计数,都可以
HashMap<String, int[]> counter5 = new HashMap<String, int[]>();		
for (String a : sArr) {
    int[] val = counter5.get(a); 		
    if (val != null) {
	val[0]++;
    } else {
	counter5.put(a, new int[]{1});
    }
}

HashMap<String, AtomicInteger> counter6 = new HashMap<String, AtomicInteger>();		
for (String a : sArr) {
    AtomicInteger val = counter6.get(a); 		
    if (val != null) {
	val.incrementAndGet();
    } else {
	counter6.put(a, new AtomicInteger(1));
    }
}

以上是使用map集合实现几种计数器,究竟哪种效率最高,可能会因搜索数据量,统计事物出现的频率,计算机等因素有所不同,根据我个人的实验,使用int[ ](counter5)最为高效。

     有兴趣的可以自己测验试试。记得砖块捡小的拍哦……

© 著作权归作者所有

有如此
粉丝 2
博文 16
码字总数 5750
作品 0
无锡
程序员
私信 提问
加载中

评论(1)

用户名已被占用
用户名已被占用
顶一个 30
java 之ThreadLocal

通过 ThreadLocal 能数据保存在一个线程中,而且不需要 lock 同步。理论上 ThreadLocal 可 以让一个变量在每个线程都有一个副本。 ThreadLocal 常用来屏蔽线程的私有变量,例如“并 发事务”或...

Beaver_
2015/04/04
167
0
JVM(二)Java虚拟机组成详解

导读:详细而深入的总结,是对知识“豁然开朗”之后的“刻骨铭心”,想忘记都难。 Java虚拟机(Java Virtual Machine)下文简称jvm,上一篇我们对jvm有了大体的认识,进入本文之后我们将具体...

王磊的博客
01/14
182
0
Java基础 之ThreadLocal

首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中...

棋逢对手
2013/01/30
123
0
JVM 深入笔记(1)内存区域是如何划分的?

JVM 深入笔记(1)内存区域是如何划分的? 作者:柳大 · Poechant 电邮:zhongchao.ustc#gmail.com (#->@) 博客:blog.csdn.net/poechant 日期:Feb. 21st 2012 一个超短的前言 JVM 是一个从...

晨曦之光
2012/04/24
198
0
JVM系列(二)—JVM内存结构

所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些...

haoyuehong
2018/12/29
67
0

没有更多内容

加载失败,请刷新页面

加载更多

数据可视化赋能大数据价值释放,助力大数据价值应用落地

今天,大数据已无所不在,并且正越来越广泛的被应用到金融、互联网、科学、电商、工业甚至渗透到我们生活的方方面面中,获取的渠道也越来越便利。 然而,很多公司企业只知道大数据的重要性,...

NBI大数据可视化
6分钟前
1
0
vim 配置 java complete

遇到的一个坑 安装好插件后,启动 Vim 时遇到过这样一个错误 No Javavi library classes found, it means that we couldn't compile it. Do you have JDK8+ installed? Failed to compile ja......

MtrS
8分钟前
0
0
收藏功能的实现

1.点击按钮,前端判断当前收藏状态;若已收藏,则发起取消收藏指令,否则发起收藏指令 2.通过接口将用户ID和商品ID传到后台 3.后端接受信息,更新对应内容的收藏数,并在收藏数据表中插入/删...

无精疯
24分钟前
3
0
idea 打开一个新的项目,maven都需要重新配置,解决方案

需要有个默认全局配置 File->Other Settings -> Default Settings 将Maven home directory目录修改成我们自定安装Maven的目录...

观海562
51分钟前
6
0
输出乘法口诀表

#include<stdio.h> #include<stdlib.h> int main(){ int a, b, c; int n = 9; for (a = 1; a <= n; a++){ for (b = 1; b <= a; b++){ c = a*b; //输出a,b,c三个数 所以格式为"%d*%d=%d" %-......

Lxxxxx256
54分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部