在处理全国人口数据时,我们常常需要统计每个年龄的人数。然而,在大数据场景下,这个任务并不简单。假设我们有如下条件:

  • 文件中包含几十亿条年龄数据;
  • 年龄为整数,通常在 0\~150 岁范围内
  • 机器条件有限:单台 2 CPU + 2G 内存
  • 禁止使用现成容器(如 HashMap),只能使用数组或其他基础数据结构

一、问题分析

数据特点

  1. 年龄范围有限
    人口年龄通常在 0~150 岁之间,属于整数类型。

  2. 数据量巨大
    全国人口几十亿条记录,无法一次性全部加载到内存。

机器限制

  1. 内存受限
    内存仅 2G,无法存储所有数据到内存中进行统计。写算法需要考虑空间复杂度,避免OOM

  2. 禁止使用 Map
    只能使用数组或其他简单数据结构进行统计。


二、最优算法思路

方法:数组计数法(Counting Array)

原理
  • 年龄是整数且范围固定 → 可以用数组下标表示年龄
  • 数组 元素存储该年龄的人数
  • 每读取一条年龄数据,对应数组下标的值加 1。
实现示例(Java)
int MAX_AGE = 150; // 假设最大年龄为150
long[] ageCount = new long[MAX_AGE + 1]; // 使用long防止人口过大溢出

// 逐行读取文件数据
try (BufferedReader br = new BufferedReader(new FileReader("ages.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        int age = Integer.parseInt(line.trim());
        ageCount[age]++;
    }
}

// 输出统计结果
for (int i = 0; i <= MAX_AGE; i++) {
    if (ageCount[i] > 0) {
        System.out.println(i + ": " + ageCount[i]);
    }
}

方法优点

  1. 内存占用固定
    只需存储 151 个 long,约 1.2 KB,非常节省。

  2. 时间复杂度低

    • 读取文件逐行处理:O(n),n 为文件中的总记录数;
    • 输出结果遍历数组:O(MAX_AGE),MAX_AGE = 150,可忽略不计。
      • 遍历数组输出结果可以认为是 O(1),因为 MAX_AGE 是固定常数,不会随着数据规模变化
    • 总体时间复杂度:O(n)
  3. 实现简单
    不需要复杂的数据结构,直接使用数组即可。


注意事项

  1. 人口数量可能很大
    使用 long 类型存储计数,避免溢出。

  2. 适用场景

    • 统计范围固定、值为整数的数据,如年龄、评分等级等。
    • 数据量大,但数值范围小。

三、总结

在大数据场景下,数组计数法是一种高效、节省内存的统计手段。它充分利用了问题特点:

  • 整数范围固定 → 可映射到数组下标;
  • 计数数据量大 → 数组大小远小于数据量,满足低内存需求;
  • 时间复杂度 O(n) → 线性处理数据,即便数据量几十亿条,也可快速统计。

在理想情况下,统计 13 亿条年龄数据的耗时主要由磁盘 I/O 决定:假设每条记录平均 3 字节,总文件约 3.9 GB,普通机械硬盘顺序读取约 100 MB/s → 读取约 40 秒,SSD 顺序读取约 500 MB/s → 读取约 8 秒,而 CPU 的数组计数操作非常快,只增加几秒,总耗时分别约 45 秒和 10 秒左右。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐