扫码关注官方订阅号
正文
0
聖光之護
发布时间:2025-07-21 21:26:01
448人浏览过
来源于php中文网
原创
在java中,java.util.hashmap是一种常用的键值对存储结构。然而,hashmap的内部实现是基于哈希表,它不保证元素的迭代顺序。这意味着当你将excel表格中的列名和值存入hashmap时,即使你按照从左到右的顺序插入,hashmap在迭代时也可能以任意顺序返回这些键值对。这对于需要严格保持列顺序的场景(如将数据写回excel或按原顺序处理数据)来说,是一个显著的问题。
例如,一个Excel表格的列顺序是 column1, column2:
column1 column2 value1 value2 value3 value4
如果使用HashMap存储,得到的Map可能呈现如下无序状态:
0 = "column2" -> value2 "column1" -> value1 1 = "column2" -> value4 "column1" -> value3
这与我们期望的 column1 -> value1, column2 -> value2 的顺序不符。
为了解决HashMap的无序性问题,Java提供了java.util.LinkedHashMap。LinkedHashMap继承自HashMap,并额外维护了一个双向链表,用于记录元素的插入顺序。因此,当你遍历LinkedHashMap时,它会按照键值对被插入的顺序返回它们。这正是我们读取Excel数据并希望保持列顺序所需的特性。
立即学习“Java免费学习笔记(深入)”;
免费的实时语音转换器和调制器
以下是修改后的readExcelSheet方法,它将HashMap替换为LinkedHashMap,以确保列的顺序得到保留。
import org.apache.poi.ss.usermodel.*; import java.util.*; public class ExcelReaderUtil { /** * 从Excel工作表中读取数据,并以有序的List<Map<String, String>>形式返回。 * 每个Map代表一行数据,Map中的键值对顺序与Excel列的插入顺序一致。 * * @param sheet 要读取的Excel工作表对象 * @return 包含Excel数据的List,如果工作表为空则返回空列表 */ public static List<Map<String, String>> readExcelSheet(Sheet sheet) { // 获取行的迭代器 Iterator<Row> rows = sheet.iterator(); // 如果没有行,则返回空列表 if (!rows.hasNext()) { return Collections.emptyList(); } // 读取表头(第一行)作为Map的键 Row header = rows.next(); List<String> keys = new ArrayList<>(); // 遍历表头单元格,获取列名 for (Cell cell : header) { String value = getCellValueAsString(cell); // 使用辅助方法获取单元格值 if (!value.isEmpty()) { keys.add(value); } else { // 遇到空列名时,可以根据实际需求选择跳出或继续 // 这里选择跳出,认为后续列可能不再是有效表头 break; } } // 初始化结果列表 List<Map<String, String>> result = new ArrayList<>(); // 遍历剩余的每一行数据 while (rows.hasNext()) { Row row = rows.next(); // 使用LinkedHashMap来保证列的插入顺序 Map<String, String> rowMap = new LinkedHashMap<>(); // 遍历表头键,按顺序填充当前行的数据 for (int i = 0; i < keys.size(); ++i) { // 获取单元格,如果不存在则创建为空白单元格 Cell cell = row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); String value = getCellValueAsString(cell); // 使用辅助方法获取单元格值 rowMap.put(keys.get(i), value); } // 只有当行不为空时才添加到结果列表 // 判断行是否为空:检查Map中所有值是否都为空字符串 if (!rowMap.values().stream().allMatch(String::isEmpty)) { result.add(rowMap); } } return result; } /** * 辅助方法:安全地获取单元格的字符串值,处理不同类型的单元格。 * * @param cell 单元格对象 * @return 单元格的字符串表示,如果单元格为null或空白,则返回空字符串 */ private static String getCellValueAsString(Cell cell) { if (cell == null) { return ""; } switch (cell.getCellType()) { case STRING: return cell.getStringCellValue(); case NUMERIC: // 对于日期类型,需要额外处理,这里简化为数值 if (DateUtil.isCellDateFormatted(cell)) { return cell.getDateCellValue().toString(); // 或者格式化为特定日期字符串 } else { return String.valueOf(cell.getNumericCellValue()); } case BOOLEAN: return String.valueOf(cell.getBooleanCellValue()); case FORMULA: // 对于公式单元格,可以尝试获取计算后的值 try { return String.valueOf(cell.getNumericCellValue()); // 尝试获取数值结果 } catch (IllegalStateException e) { try { return cell.getStringCellValue(); // 尝试获取字符串结果 } catch (IllegalStateException ex) { return ""; // 无法获取值 } } case BLANK: return ""; default: return ""; // 默认返回空字符串 } } // 示例用法 (需要Apache POI库) public static void main(String[] args) throws Exception { // 假设有一个名为 "example.xlsx" 的Excel文件 // 创建一个模拟的Workbook和Sheet用于测试 Workbook workbook = new org.apache.poi.xssf.usermodel.XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet1"); // 创建表头 Row headerRow = sheet.createRow(0); headerRow.createCell(0).setCellValue("column1"); headerRow.createCell(1).setCellValue("column2"); headerRow.createCell(2).setCellValue("column3"); // 增加一列测试 // 创建数据行1 Row dataRow1 = sheet.createRow(1); dataRow1.createCell(0).setCellValue("value1"); dataRow1.createCell(1).setCellValue("value2"); dataRow1.createCell(2).setCellValue(123); // 测试数值类型 // 创建数据行2 Row dataRow2 = sheet.createRow(2); dataRow2.createCell(0).setCellValue("value3"); dataRow2.createCell(1).setCellValue("value4"); dataRow2.createCell(2).setCellValue(true); // 测试布尔类型 // 创建空行(应被过滤) sheet.createRow(3); // 调用读取方法 List<Map<String, String>> data = readExcelSheet(sheet); // 打印结果,观察列顺序 for (Map<String, String> rowMap : data) { System.out.println("--- Row ---"); rowMap.forEach((key, value) -> System.out.println(" " + key + " -> " + value)); } workbook.close(); } }
代码改进说明:
除了LinkedHashMap,Java还提供了其他Map实现,它们在特定场景下也可能有用:
<!-- Maven --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.3</version> <!-- 使用最新稳定版本 --> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> <!-- 处理.xlsx文件需要此依赖 --> </dependency>
通过将HashMap替换为LinkedHashMap,可以有效地解决在Java中读取Excel数据时列顺序混乱的问题,确保数据在内存中保持与源文件一致的结构,从而简化后续的数据处理和回写操作。
相关文章
如何配置Java编程的Apache Shiro安全环境_Java权限管理
Apache Camel 中基于消息头条件实现消息复制的完整指南
Apache HttpClient 5 中配置重定向时保留敏感请求头的完整指南
Apache Beam Java 实现 JSON 数据按键聚合合并教程
java成品网站能二次开发吗 java成品网站二次开发可行性
相关标签:
本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
如何在页面刷新后持久化保存复选框的选中状态
2026-03-09 13:20
Go 程序中 HTTP 连接复用导致内存持续增长的解决方案
2026-03-09 13:22
Python正则表达式中字符类内连字符(-)的位置规则详解
2026-03-09 13:24
一键启动!KiriGiri发布D加密虚拟机破解启动器
2026-03-09 13:33
Python中批量替换列表中所有匹配元素的正确方法
2026-03-09 13:41
如何在 Pandas 中安全获取首个存在的列值(避免 KeyError)
2026-03-09 13:54
如何在时间类中保留原始输入值以实现准确的总秒数计算
2026-03-09 13:56
《杀戮尖塔2》Steam峰值超57万 成2026年首发最高游戏
2026-03-09 13:59
如何在单页中正确结合 AJAX 与 PHP 实现用户名实时校验
2026-03-09 14:01
壹心理如何提问
2026-03-09 14:15
热门AI工具
幻方量化公司旗下的开源大模型平台
字节跳动自主研发的一系列大型语言模型
阿里巴巴推出的全能AI助手
腾讯混元平台推出的AI助手
文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。
基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿
一站式AI创作平台,免费AI图片和视频生成。
最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。
智谱清言 - 免费全能的AI助手
相关专题
本专题聚焦 Java 主流构建工具 Maven 的学习与应用,系统讲解项目结构、依赖管理、插件使用、生命周期与多模块项目配置。通过企业管理系统、Web 应用与微服务项目实战,帮助学员全面掌握 Maven 在 Java 项目构建与团队协作中的核心技能。
2025.09.15
在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。
1010
2023.08.02
if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。
846
2023.08.22
本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。
120
2025.10.15
本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。
261
2025.10.24
js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。
760
2023.08.03
js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。
221
2023.09.04
java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。
1566
2023.10.24
本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。
3
2026.03.11
热门下载
相关下载
精品课程
共22课时 | 1.8万人学习
共18课时 | 3.3万人学习
共14课时 | 3.2万人学习
共6课时 | 11.3万人学习
共79课时 | 153.9万人学习
共6课时 | 53.6万人学习
共4课时 | 22.5万人学习
共13课时 | 1.0万人学习
最新文章
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部