You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java读取超大型CSV文件,按访问方式统计子用户数量

大CSV文件子用户访问方式统计实现方案

核心思路

因为文件超2GB、2000万+记录,绝对不能一次性把整个文件加载到内存,必须用流式逐行解析,配合轻量的统计容器(子用户仅200+,内存占用可忽略)。

具体实现步骤

1. 选择轻量CSV解析库

推荐用Apache Commons CSV,它支持流式读取,避免内存溢出。Maven依赖如下:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.10.0</version>
</dependency>

2. 流式读取+统计代码

假设CSV列格式为子用户ID,访问方式,代码逻辑如下(可根据实际列名调整):

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class CsvUserStats {
    public static void main(String[] args) {
        // 初始化统计Map,已知子用户200+,设初始容量300避免扩容开销
        Map<String, Integer> userCountMap = new HashMap<>(300);
        String csvFilePath = "你的目标文件路径.csv";

        try (FileReader reader = new FileReader(csvFilePath);
             // 配置CSV格式,指定表头列名,自动跳过第一行表头
             CSVParser parser = CSVFormat.DEFAULT
                     .withHeader("子用户ID", "访问方式")
                     .withFirstRecordAsHeader()
                     .parse(reader)) {

            // 逐行解析处理
            for (CSVRecord record : parser) {
                String userId = record.get("子用户ID");
                // 按子用户统计总访问数(若需按访问方式细分,可将键设为userId+"_"+访问方式)
                userCountMap.put(userId, userCountMap.getOrDefault(userId, 0) + 1);
            }

            // 输出统计结果
            for (Map.Entry<String, Integer> entry : userCountMap.entrySet()) {
                System.out.println(entry.getKey() + "计数" + entry.getValue());
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 关键优化点

  • 流式处理:用try-with-resources自动管理流资源,逐行读取解析,内存仅占用当前行数据+统计Map(几KB级别)
  • 编码适配:若CSV为GBK等非UTF-8编码,替换FileReader为new InputStreamReader(new FileInputStream(csvFilePath), "GBK")
  • 无效行过滤:循环内可增加判断,跳过子用户ID为空的无效行
  • 线程安全(可选):若用并行流处理,将HashMap替换为ConcurrentHashMap保证线程安全

4. 原生Java备用方案(无第三方库)

若不想引入依赖,可手动逐行读取,但需注意CSV字段含逗号的场景(比如引号包裹的字段)会出错,仅适用于简单格式:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class RawCsvStats {
    public static void main(String[] args) {
        Map<String, Integer> userCountMap = new HashMap<>(300);
        String csvFilePath = "你的目标文件路径.csv";

        try (BufferedReader br = new BufferedReader(new FileReader(csvFilePath))) {
            // 跳过表头
            br.readLine();
            String line;
            while ((line = br.readLine()) != null) {
                String[] parts = line.split(",");
                if (parts.length >= 2) {
                    String userId = parts[0].trim();
                    userCountMap.put(userId, userCountMap.getOrDefault(userId, 0) + 1);
                }
            }

            // 输出结果
            userCountMap.forEach((k, v) -> System.out.println(k + "计数" + v));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注意事项

  • 避免用Excel类库(如POI)处理大CSV,这类库内存开销极大
  • 无需额外调大JVM内存,默认堆内存即可支撑
  • 串行版本处理2000万条记录仅需数分钟,新手优先保证串行版本跑通再考虑并行优化

内容的提问来源于stack exchange,提问作者Runtime21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 18:53:19