避免Java中的大量计数器

避免Java中的大量计数器,java,sql,database,csv,count,Java,Sql,Database,Csv,Count,在我的Java项目中,我需要读取一个大约160万行的文件 每行表示用户在一天内完成的一个操作。如果我没有错,有83种不同的可能行动 我需要按如下方式分析该文件,并将找到的统计信息存储在csv文件中: 一般来说:计算一个动作发生的频率(数字将高达50万) 但也应该有单独的文件: 每小时发生一次操作的频率是多少?(csv文件中有24行) 每个用户执行一个操作的频率是多少?(大约20个不同的用户-每个用户一个文件) 每个用户每小时执行一次操作的频率是多少?(每个用户有单独的文件,其中有24行) 最

在我的Java项目中,我需要读取一个大约160万行的文件

每行表示用户在一天内完成的一个操作。如果我没有错,有83种不同的可能行动

我需要按如下方式分析该文件,并将找到的统计信息存储在
csv
文件中: 一般来说:计算一个动作发生的频率(数字将高达50万)

但也应该有单独的文件:

  • 每小时发生一次操作的频率是多少?(csv文件中有24行)

  • 每个用户执行一个操作的频率是多少?(大约20个不同的用户-每个用户一个文件)

  • 每个用户每小时执行一次操作的频率是多少?(每个用户有单独的文件,其中有24行)

最重要的是,有3个不同的频道(HTML、手机、电话)可以发生这些事情(也保存在日志文件中),因此我需要为每个频道创建一个文件夹,并为每个频道执行上面提到的操作

问题:

我如何有效地存储/计算这些数据?运行时间不是什么大问题(它不应该运行一天,但没问题,它需要半个小时) 但是我怎么计算呢

我不能只为每件事创建那么多计数器(数量将是巨大的),在我看来,
int[]
在这里不是很方便,因为我必须记住哪个操作有哪个索引等

有更好的解决办法吗

我曾考虑使用本地数据库和
SQ
L脚本,但该程序需要在每台PC上运行,并且必须从命令行(不一定在IDE中)执行。我正在使用Intellij 14进行开发。

A
HashMap
将是您柜台的便捷工具。对于所有操作类型,一个实例就足够了

关于工作流,您有以下选择:

  • 将完整的文件加载到RAM中(随着今天RAM的大小,这种方法变得越来越流行),然后根据需要对其进行分析

  • 对于每种类型的分析,请再次读取该文件

  • 如果你的目标是较旧、设备较少的计算机,那么秒的选择似乎不错


    顺便说一下,如果您可以使用Java8,我强烈建议您使用Streams API进行分析。它将从您的代码中删除大量样板文件,您将获得有效利用Streams API的重要技能。

    类似嵌入式数据库

    任何包装都意味着你必须自己做每件事

    您可以在多个级别上计算字段,可能作为单独的表,以提高速度。带有时间戳以供检查

    优点是可以灵活地完成报告。备份很容易


    当一切正常时,可以稍后进行自定义重构。

    我将介绍一个KeyClass

    public KeyClass {
      timeInterval;
      user;
      action;
      channel;
    
      hasCode();
      equals();
    }
    
    在地图上用它来计数。 对于每个记录,创建键实例并从映射值中获取。增加值(或为缺少的关键点创建)

    然后使用映射聚合计数

    更新:

    Map<KeyClass, Integer> map=new HashMap<>();
    for (String oneLine: allLines) {
        KeyClass lineKey=createSomeHowTheKeyFromLine(oneLine);
        Integer value=map.get(lineKey);
        if (value==null) {
           value=0;
        }
        value++;
        map.put(lineKey, value);
    }
    
    Map Map=newhashmap();
    用于(字符串单行:所有行){
    KeyClass lineKey=createSomeHowTheKeyFromLine(一行);
    整数值=map.get(lineKey);
    如果(值==null){
    数值=0;
    }
    值++;
    map.put(lineKey,value);
    }
    

    循环结束后,您的所有计数都在映射中。

    假设每个操作都有一个唯一的名称(或id),您应该将计数器存储在映射中,而不是存储在数组中,以避免出现“记住哪个操作有哪个索引”的问题。有趣的想法是,您将如何实现它?该文件为我提供了操作名称(83个可能性-例如,其中一个可能是“登录”)、发生时间(HHMMSS)、频道(HTML/MOBILE/PHONE)和用户ID,无论您在哪里运行它,除非运行某种服务器并连接到要使用的每个客户机,否则您将无法使用SQL或Java属性。。。我不明白你想如何存储一些已经创建的东西?比如说每个动作都有一个文件,它的数量是多少?这可能有助于进一步解释这个过程。每天早上,都会有一个来自公司的大日志文件,在过去的一天里每天都应该对它进行分析,并存储在csv文件中。分析不会发生在我的工作PC上,这就是为什么我希望它能在其他电脑上运行。虽然它总是在同一台电脑上,但我真的无法访问它。因此,数据库(如果我必须使用一个)应该本地存储在项目文件或其他文件中,以便我可以将其复制到“分析PC”中,并在那里工作。无需实现它,它随时可供您使用
    Map counterByAction=newhashmap。这种键定义意味着您从未两次击中同一计数器。您的
    KeyClass
    实际上适合作为一行输入文件的域模型,可以存储在
    Set
    中。更新的答案只是重申了错误的建议。结果将是一个映射,其键数与文件中的行数相同,并且所有值都等于1(除了完全重复的行)。显然,OP正在寻找一些完全不同的东西。是的,尽管数据库文件通常是在用户主目录中创建的,可能在创建的子目录中:
    new file(System.getProperty(“user.home”)+“/.timidly”).mkdirs()中。方案创建和初始数据可以在启动时完成。