场景题 如何Java用内存200M的情况下读取1G文件,并统计重复内容?

发布于:2025-05-19 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

一、流式读取与内存控制

二、高效去重数据结构

三、内存优化补充策略

四、性能与监控

五、完整示例代码

引用与扩展


最近在面试的时候碰到的一个场景题

在Java中处理1GB大文件并统计重复内容,需结合流式读取和内存优化技术。根据内存200MB限制,以下是分步骤解决方案及关键技术点:


一、流式读取与内存控制

逐行读取技术
使用

  1. BufferedReaderScanner实现流式处理,避免一次性加载文件。示例代码:
try (BufferedReader br = new BufferedReader(new FileReader("large.txt"),  8192)) {
    String line;
    while ((line = br.readLine())  != null) {
        // 处理每行数据 
    }
}
    • 内存消耗:仅需约20MB缓冲(取决于缓冲区大小)。
  1. 字符编码处理
    明确指定编码(如UTF-8)避免解析错误:
BufferedReader br = new BufferedReader(
    new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)
);

二、高效去重数据结构

  1. BitSet去重法
    • 原理:每个数字对应一个二进制位,若位值为1则表示已存在,否则标记为1。
    • 内存优势:9亿数字仅需约112MB内存(9e8 bits ≈ 107MB)。
    • 示例代码
BitSet bitSet = new BitSet();
int num = Integer.parseInt(line); 
if (bitSet.get(num))  {
    // 统计重复 
    duplicateCount++;
} else {
    bitSet.set(num); 
}
  1. 适用条件
    • 数字范围在整数范围内(0~2^31-1)。
    • 若数字范围过大,需分片处理(如哈希分片到多个BitSet)。

三、内存优化补充策略

  1. 分治处理(可选)
    若数字范围超限,采用哈希分片写入临时文件,再逐个处理小文件:
int hash = Math.abs(line.hashCode())  % 1000;
writeToTempFile(line, "shard_" + hash + ".tmp");
  1. Bloom Filter(允许误判时)
    若允许一定误判率,使用布隆过滤器进一步压缩内存:
BloomFilter<Integer> filter = BloomFilter.create(Funnels.integerFunnel(),  1e9, 0.01);
if (filter.mightContain(num))  {
    // 可能重复 
}

四、性能与监控

  1. 垃圾回收调优
    • 年轻代(Young Generation)设置为较小空间(如50MB),减少Full GC频率。
    • JVM参数示例:-Xmx200m -XX:NewSize=50m
  1. 监控工具
    使用VisualVM或JConsole观察内存占用,确保老年代(Old Generation)稳定在130MB以内。

五、完整示例代码

public class Deduplicator {
    public static void main(String[] args) throws IOException {
        BitSet bitSet = new BitSet();
        int duplicates = 0;
 
        try (BufferedReader br = new BufferedReader(
                new FileReader("large.txt"),  8192)) {
            String line;
            while ((line = br.readLine())  != null) {
                int num = Integer.parseInt(line.trim()); 
                if (bitSet.get(num))  {
                    duplicates++;
                } else {
                    bitSet.set(num); 
                }
            }
        }
 
        System.out.println(" 重复次数: " + duplicates);
    }
}

引用与扩展

  • 关键参考:验证了BitSet方案的实际内存占用,提供了流式读取的优化方法,总结了避免内存溢出的通用原则。
  • 扩展场景:若需排序,可结合外排序(External Sort)和归并策略。

网站公告

今日签到

点亮在社区的每一天
去签到