1. 将 2GB 的大文件分割为 2048 个大小为 512KB 的小文件,采用流式读取方式处理,避免一次性加载整个文件导致内存溢出。

  2. 初始化一个长度为 2048 的哈希表数组,用于分别统计各个小文件中单词的出现频率。

  3. 利用多线程并行处理机制遍历所有 2048 个小文件,对每个文件中的单词执行哈希取模运算(int hash = Math.abs(word.hashCode() % hashTableSize)),并通过hashTables[hash].merge(word, 1, Integer::sum)的方式将单词频率累加到对应的哈希表中。

  4. 遍历这 2048 个哈希表,对每个哈希表中的单词按频率排序,将频率排名前 100 的单词存入一个小顶堆。

  5. 经过上述处理后,小顶堆中最终保留的 100 个单词即为整个文件中出现频率最高的前 100 个单词。

package com.example.bigfiletop100;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;public class Top100Words {private static final int HASH_TABLE_SIZE = 2048;private static final int TOP_WORDS_COUNT = 100;public static void main(String[] args) throws IOException, InterruptedException {String largeFilePath = "C:\\Users\\亚洲\\IdeaProjects\\springboot-easyexcel-mybatisplus\\src\\main\\java\\com\\example\\bigfiletop100\\input.txt"; // 替换为大文件的路径String tempDirPath = "C:\\Users\\亚洲\\IdeaProjects\\springboot-easyexcel-mybatisplus\\src\\main\\java\\com\\example\\bigfiletop100\\temp_files"; // 替换为临时目录的路径Path tempDir = Paths.get(tempDirPath);if (!Files.exists(tempDir)) {Files.createDirectories(tempDir);}// 1. 分割大文件为512KB的小文件(改进版)splitFile(largeFilePath, tempDir.toString(), 512 * 1024);// 2. 初始化哈希表数组ConcurrentHashMap<Integer, Map<String, Integer>> hashTables = new ConcurrentHashMap<>();for (int i = 0; i < HASH_TABLE_SIZE; i++) {hashTables.put(i, new ConcurrentHashMap<>());}// 3. 并行遍历小文件,统计单词频率File[] smallFiles = new File(tempDir.toString()).listFiles((dir, name) -> name.endsWith(".txt"));if (smallFiles == null || smallFiles.length == 0) {System.err.println("No small files found.");return;}ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());CountDownLatch latch = new CountDownLatch(smallFiles.length);for (File smallFile : smallFiles) {executor.submit(() -> {try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(smallFile), StandardCharsets.UTF_8))) {String line;while ((line = reader.readLine()) != null) {String[] words = line.trim().split("\\s+");for (String word : words) {if (word.isEmpty()) continue;int hash = Math.abs(word.hashCode() % HASH_TABLE_SIZE);hashTables.get(hash).merge(word, 1, Integer::sum);}}} catch (IOException e) {System.err.println("Error reading file: " + smallFile.getName());e.printStackTrace();} finally {latch.countDown();}});}executor.shutdown();latch.await(); // 等待所有任务完成// 4. 合并哈希表,并把频率前100的单词存入小顶堆PriorityQueue<Map.Entry<String, Integer>> minHeap = new PriorityQueue<>(TOP_WORDS_COUNT,(o1, o2) -> o1.getValue().compareTo(o2.getValue()));hashTables.values().stream().filter(Objects::nonNull).flatMap(map -> map.entrySet().stream()).forEach(entry -> {if (minHeap.size() < TOP_WORDS_COUNT) {minHeap.offer(entry);} else if (entry.getValue() > minHeap.peek().getValue()) {minHeap.poll();minHeap.offer(entry);}});// 5. 输出结果System.out.println("Top " + TOP_WORDS_COUNT + " words:");List<Map.Entry<String, Integer>> topWords = new ArrayList<>(minHeap);topWords.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue())); // 按降序排列topWords.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));// 清理临时文件和目录Arrays.stream(smallFiles).forEach(File::delete);Files.deleteIfExists(tempDir);}private static void splitFile(String largeFilePath, String tempDir, int size) throws IOException {try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(largeFilePath))) {byte[] buffer = new byte[size];int bytesRead;int fileCount = 0;while ((bytesRead = bis.read(buffer)) != -1) {File smallFile = new File(tempDir, "part-" + fileCount++ + ".txt");// 避免截断单词int actualBytesRead = bytesRead;if (bytesRead <= size && buffer[bytesRead - 1] != '\n') {// 查找最后一个空格或换行符作为分割点for (int i = bytesRead - 1; i >= 0; i--) {if (buffer[i] == ' ' || buffer[i] == '\n') {actualBytesRead = i + 1;bis.reset();bis.skip(actualBytesRead);break;}}}try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(smallFile))) {bos.write(buffer, 0, actualBytesRead);}}}}
}

关键说明

  1. 文件分割优化
    分割时避免截断单词(通过查找最后一个非字母位置),确保每个单词完整属于一个小文件,避免统计误差。

  2. 内存控制
    单个小文件 512KB,2G 文件约 4096 个小文件(而非 2048,更保守),每个小文件单独处理,避免 OOM。

  3. 多线程效率
    使用线程池(大小为 CPU 核心数)并行处理小文件,提升统计速度,哈希表数组避免线程竞争(每个哈希槽独立)。

  4. 小顶堆筛选
    堆大小固定为 100,每次插入复杂度 O (log 100),整体效率远高于全量排序(O (n log n))。

  5. 单词处理
    统一转为小写(忽略大小写差异),用正则提取纯字母单词(可根据需求调整匹配规则,如保留数字)。

此方案适用于大文件场景,通过分治思想将问题拆解为可并行处理的子任务,再通过堆排序高效筛选结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916526.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916526.shtml
英文地址,请注明出处:http://en.pswp.cn/news/916526.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于LNMP分布式个人云存储

1.准备工作a.关闭两台虚拟机的安全软件客户端&#xff1a;[rootmaster ~]# systemctl stop firewalld [rootmaster ~]# systemctl disable firewalld [rootmaster ~]# systemctl status firewalld ○ firewalld.service - firewalld - dynamic firewall daemonLoaded: loaded (…

指针运算全攻略:加减、比较与排序

常见的指针指针运算说明1.指针与整数的加减运算对指针可以进行加法运算&#xff0c;即p n或者p - n。其结果依旧是一个是一个指针&#xff0c;新的指针是在原来的地址值基础上加上/减去n *(sizeof(指针指向的数据类型)&#xff09;个字节。示例&#xff1a;#include<stdio.…

物联网安装调试-物联网网关

物联网网关作为连接终端设备与云平台的核心枢纽,其分类与选型需结合功能定位、硬件性能、连接方式及应用场景等多维度考量。以下从分类体系和产品推荐两方面系统梳理,助您高效决策: 🔧 一、物联网网关分类体系 1. 按功能定位划分 类型 核心能力 典型场景 代表产品 边缘计…

Jenkins教程(自动化部署)

Jenkins教程(自动化部署) 1. Jenkins是什么&#xff1f; Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具&#xff0c;广泛用于项目开发&#xff0c;具有自动化构建、测试和部署等功能。Jenkins用Java语言编写&#xff0c;可在Tomcat等流行的servlet容器中运行&…

linux 驱动验证是否成功 之 查看moudle信息

这些是 Linux 内核模块&#xff08;.ko&#xff09;中的元信息&#xff08;metadata&#xff09;&#xff0c;可以通过如下方式查看&#xff1a;✅ 1. 使用 modinfo 命令查看已加载或已编译模块信息 示例&#xff1a; modinfo aw2013.ko输出内容大概如下&#xff1a; filename:…

浏览器关闭之前请求接口到后端

2025.07.24今天我学习了如何在浏览器关闭之前请求一个接口返回到后端。可以用performance.navigation判断是浏览器关闭&#xff0c;还是浏览器刷新&#xff0c;因为我这边只需要浏览器关闭的时候才去触发1. 利用performance API&#xff08;刷新检测&#xff09; 刷新页面时&am…

MySQL批量数据处理与事务管理

MySQL是一种广泛应用的关系型数据库管理系统&#xff0c;尤其在数据分析和业务逻辑处理方面具有重要地位。在数据量庞大的业务场景中&#xff0c;批量数据处理和事务管理是提高效率和保障数据一致性的重要手段。掌握高效的批量数据操作方法与事务管理技巧&#xff0c;不仅能够提…

iOS网络之异步加载

为什么你的图片要异步加载&#xff1f;在仿写天气预报时&#xff0c;我们常常需要从网络加载天气图标&#xff0c;例如显示某个小时的天气状态图标。这看似简单的事情&#xff0c;如果处理不当&#xff0c;却很容易造成界面卡顿&#xff0c;甚至影响整个 App 的用户体验。错误做…

C#值类型属性的典型问题

问题复现&#xff1a;值类型属性的副本问题以下代码展示了值类型属性的典型问题&#xff1a;struct Point {public int X;public int Y; }class MyClass {public Point Position {get; set;} }// 使用属性修改结构体&#xff08;无效&#xff01;&#xff09; var obj new MyC…

机器学习基础-k 近邻算法(从辨别水果开始)

一、生活中的 "分类难题" 与 k 近邻的灵感 你有没有这样的经历&#xff1a;在超市看到一种从没见过的水果&#xff0c;表皮黄黄的&#xff0c;拳头大小&#xff0c;形状圆滚滚。正当你犹豫要不要买时&#xff0c;突然想起外婆家的橘子好像就是这个样子 —— 黄色、圆…

【WPF】NumericUpDown的用法

在 WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;NumericUpDown 控件并不是内置的标准控件之一&#xff0c;但它是一个非常常用的控件&#xff0c;用于让用户输入一个数值&#xff08;整数或浮点数&#xff09;&#xff0c;并提供上下箭头来递增或…

Kotlin位运算

Kotlin 提供了几种用于操作整数各个位&#xff08;bit&#xff09; 的运算符。这些操作是由处理器直接支持的&#xff0c;速度快且操作简单。在底层编程中非常重要&#xff0c;比如设备驱动、低级图形处理、网络通信、加密和压缩等。 尽管计算机通常都有高效的硬件指令来执行算…

墨者:通过手工解决SQL手工注入漏洞测试(MongoDB数据库)

一、SQL手工注入漏洞测试(MongoDB数据库) 本文以墨者学院靶场为例&#xff0c;演示MongoDB数据库的手工SQL注入全过程。靶场以自己的地址为准&#xff1a;http://124.70.71.251:42286/new_list.php?id1 二、注入原理说明 MongoDB作为NoSQL数据库&#xff0c;其注入方式与传…

Kafka——CommitFailedException异常处理深度解析

引言在分布式消息系统Kafka的生态中&#xff0c;消费者组&#xff08;Consumer Group&#xff09;机制是实现高吞吐量和负载均衡的核心设计。然而&#xff0c;消费过程中位移提交&#xff08;Offset Commit&#xff09;的稳定性始终是开发者面临的最大挑战之一。当消费者尝试提…

kafka的部署和jmeter连接kafka

zookeeper的安装 kafka依赖Zookeeper所以要先安装Zookeeper kafka的安装文章引用来源:Kafka下载和使用&#xff08;linux版&#xff09;-CSDN博客 通过wget命令安装 # 安装wget https://downloads.apache.org/zookeeper/stable/apache-zookeeper-3.7.1-bin.tar.gz# 解压tar…

Android UI 组件系列(八):ListView 基础用法与适配器详解

博客专栏&#xff1a;Android初级入门UI组件与布局 源码&#xff1a;通过网盘分享的文件&#xff1a;Android入门布局及UI相关案例 链接: https://pan.baidu.com/s/1EOuDUKJndMISolieFSvXXg?pwd4k9n 提取码: 4k9n 一、引言 在上一篇文章《Android UI 组件系列&#xff08;…

Android学习专题目录(持续更新)

1.Android 调试 1.1&#xff1a;Logcat日志分析 2.Android编译 2.1&#xff1a;android编译过程中的mk文件和bp文件的扫描机制 2.2&#xff1a;Android 构建系统中常见的 .mk 文件及其作用 2.3&#xff1a;Android构建系统中的mk文件语法函数 2.4&#xff1a;安卓中定…

c#Lambda 表达式与事件核心知识点整理

一、Lambda 表达式1. 概念 Lambda 表达式是一种匿名函数&#xff08;无名称的函数&#xff09;&#xff0c;简化了委托和匿名方法的写法&#xff0c;格式为&#xff1a; (参数列表) > 表达式或语句块 它可以作为参数传递&#xff0c;或赋值给委托类型变量。2. 基本语法与简写…

Springboot+Layui英语单词学习系统的设计与实现

文章目录前言详细视频演示具体实现截图后端框架SpringBootLayUI框架持久层框架MyBaits成功系统案例&#xff1a;参考代码数据库源码获取前言 博主介绍:CSDN特邀作者、985高校计算机专业毕业、现任某互联网大厂高级全栈开发工程师、Gitee/掘金/华为云/阿里云/GitHub等平台持续输…

主要分布于内侧内嗅皮层的层Ⅲ的边界向量细胞(BVCs)对NLP中的深层语义分析的积极影响和启示

边界向量细胞&#xff08;Boundary Vector Cells, BVCs&#xff09;主要分布于内侧内嗅皮层&#xff08;MEC&#xff09;层Ⅲ&#xff0c;通过编码环境边界&#xff08;如墙壁、障碍物&#xff09;的距离和方向信息&#xff0c;为空间导航提供几何参考框架。这一神经机制对自然…