java-计数器

简介: 第一种,最直观的计数器每次循环都去检查Map中是否包含Key,如果包含则将原值+1再保存,如果不存在,则直接保存1.这种方式是最简单直接的一种方式,但是并不是最有效的方式,其低效的原因: 1、如果已经存在某个key(a),containsKey()和get()方法会扫描Map两次2、由于Integer是不可变对象,因此每次循环,都会创建一个新的对象放到Map中。

第一种,最直观的计数器

每次循环都去检查Map中是否包含Key,如果包含则将原值+1再保存,如果不存在,则直接保存1.这种方式是最简单直接的一种方式,但是并不是最有效的方式,其低效的原因:
1、如果已经存在某个key(a),containsKey()和get()方法会扫描Map两次

2、由于Integer是不可变对象,因此每次循环,都会创建一个新的对象放到Map中。

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);  
            }  
        }  
    } 

第二种,比较好的计数器

自然可以想到创建一个可变的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);  
            }  
        }  
    }  
目录
相关文章
|
Java
Java实现计数器
Java实现计数器可以使用以下代码
326 0
|
6月前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
67 2
|
5月前
|
安全 算法 Java
Java面试题:如何诊断和解决Java应用程序中的内存泄漏问题?如何实现一个线程安全的计数器?如何合理配置线程池以应对不同的业务场景?
Java面试题:如何诊断和解决Java应用程序中的内存泄漏问题?如何实现一个线程安全的计数器?如何合理配置线程池以应对不同的业务场景?
38 0
Java:从单线程计数器到多线程数据同步synchronized和原子类Atomic
Java:从单线程计数器到多线程数据同步synchronized和原子类Atomic
170 0
|
存储 Java C++
JVM - 结合代码示例彻底搞懂Java内存区域_线程栈 | 本地方法栈 | 程序计数器
JVM - 结合代码示例彻底搞懂Java内存区域_线程栈 | 本地方法栈 | 程序计数器
109 0
|
算法 Java 数据格式
JVM:Java运行时数据区域----程序计数器
JVM:Java运行时数据区域----程序计数器
106 0
JVM:Java运行时数据区域----程序计数器
JUC(二)JAVA线程池开启,等待全部执行完毕,配合计数器使用,List并发异常解决
JUC(二)JAVA线程池开启,等待全部执行完毕,配合计数器使用,List并发异常解决
JUC(二)JAVA线程池开启,等待全部执行完毕,配合计数器使用,List并发异常解决
|
Java 索引
【Java 虚拟机原理】Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )(二)
【Java 虚拟机原理】Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )(二)
138 0
【Java 虚拟机原理】Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )(二)
|
Java 数据挖掘 索引
【Java 虚拟机原理】Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )(一)
【Java 虚拟机原理】Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )(一)
162 0
【Java 虚拟机原理】Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )(一)
|
Java 索引
【Java 虚拟机原理】Class 字节码二进制文件分析 三 ( 访问和修饰标志 | 类索引 | 父类索引 | 接口计数器 | 接口表 | 字段计数器 | 字段表 )(三)
【Java 虚拟机原理】Class 字节码二进制文件分析 三 ( 访问和修饰标志 | 类索引 | 父类索引 | 接口计数器 | 接口表 | 字段计数器 | 字段表 )(三)
117 0
【Java 虚拟机原理】Class 字节码二进制文件分析 三 ( 访问和修饰标志 | 类索引 | 父类索引 | 接口计数器 | 接口表 | 字段计数器 | 字段表 )(三)