导航
电话
咨询
地图
顶部
在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数据并希望保持列顺序所需的特性。
以下是修改后的readExcelSheet方法,它将HashMap替换为LinkedHashMap,以确保列的顺序得到保留。
import org.apache.poi.ss.usermodel.*; import java.util.*; public class ExcelReaderUtil { /** * 从Excel工作表中读取数据,并以有序的List>形式返回。 * 每个Map代表一行数据,Map中的键值对顺序与Excel列的插入顺序一致。 * * @param sheet 要读取的Excel工作表对象 * @return 包含Excel数据的List,如果工作表为空则返回空列表 */ public static List> readExcelSheet(Sheet sheet) { // 获取行的迭代器 Iterator rows = sheet.iterator(); // 如果没有行,则返回空列表 if (!rows.hasNext()) { return Collections.emptyList(); } // 读取表头(第一行)作为Map的键 Row header = rows.next(); List keys = new ArrayList<>(); // 遍历表头单元格,获取列名 for (Cell cell : header) { String value = getCellValueAsString(cell); // 使用辅助方法获取单元格值 if (!value.isEmpty()) { keys.add(value); } else { // 遇到空列名时,可以根据实际需求选择跳出或继续 // 这里选择跳出,认为后续列可能不再是有效表头 break; } } // 初始化结果列表 List> result = new ArrayList<>(); // 遍历剩余的每一行数据 while (rows.hasNext()) { Row row = rows.next(); // 使用LinkedHashMap来保证列的插入顺序 Map 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> data = readExcelSheet(sheet); // 打印结果,观察列顺序 for (Map rowMap : data) { System.out.println("--- Row ---"); rowMap.forEach((key, value) -> System.out.println(" " + key + " -> " + value)); } workbook.close(); } }
代码改进说明:
除了LinkedHashMap,Java还提供了其他Map实现,它们在特定场景下也可能有用:
org.apache.poi poi 5.2.3 org.apache.poi poi-ooxml 5.2.3
通过将HashMap替换为LinkedHashMap,可以有效地解决在Java中读取Excel数据时列顺序混乱的问题,确保数据在内存中保持与源文件一致的结构,从而简化后续的数据处理和回写操作。
# ai # switch # if # 接口 # 是一个 # excel # 如果你 # 继承 # Java # String # 字符串 # 为空 # 键值对 # map # 空字符串 # 迭代 # 键值 # 遍历 # excel表格 # break # 它会 # apache # 数据处理 # 单元格 # 字符串类型 # gradle # maven
相关栏目: 【 行业资讯 】 【 网络运营 】 【 GEO优化 】 【 营销推广 】 【 SEO优化 】 【 技术教程 】 【 代码知识 】 【 AI推广 】
相关推荐: mac怎么看硬盘大小_MAC查看磁盘存储空间与文件占用【详解】 如何高效识别并拦截拼接式恶意域名 spam php本地部署后数据库连接报错_1045accessdenied错误解决方法详解【汇总】 c++ std::atomic如何保证原子性 c++ CAS操作原理【底层】 Win11系统更新失败怎么办 Win11系统更新失败解决法【步骤】 Windows10如何查看保存的WiFi密码_Win10命令行netsh wlan查询 Windows蓝屏BAD_POOL_HEADER故障详解_蓝屏池损坏错误修复指南 如何使用Golang管理跨项目依赖_Golang多模块项目依赖实践 如何使用 Python 合并文件夹内多个 Excel 文件并避免权限错误 如何高效删除 NumPy 二维数组中所有元素相同的列 Windows10怎么查看系统激活状态_Windows10激活状态查看方法【教程】 Win11怎样安装企业微信_Win11安装企业微信教程【步骤】 如何在Golang中处理模块冲突_解决依赖版本不兼容问题 Win10怎么安装AdobeAcrobat_Win10安装PDF编辑器教程【步骤】 Mac如何修复应用程序权限问题_Mac磁盘工具修复权限【教程】 微信JSAPI支付回调PHP怎么接收_处理JSAPI异步通知数据方法【指南】 php485返回数据不完整怎么办_php485数据分包重组处理方法【教程】 Win10怎么卸载爱奇艺_Win10彻底卸载爱奇艺方法【步骤】 Win11怎么开启专注模式_Windows11时钟应用Focus Session 如何在JavaScript中动态拼接PHP的base_url与jQuery变量 Python函数接口文档化_自动化说明【指导】 Win11麦克风没声音怎么设置_Win11麦克风权限及驱动修复【教程】 Win11局域网共享怎么设置 Win11文件夹网络共享教程【详解】 新手学PHP架构总混淆概念咋办_重点梳理【教程】 Win11怎么激活Windows10_Win11激活Win10系统方法【步骤】 php8.4匿名类怎么用_php8.4匿名类创建与使用场景【介绍】 Win11怎么关闭小组件_Win11禁用任务栏天气与小组件方法【设置】 PHP怎么接收URL中的锚点参数_获取#后面参数值的技巧【详解】 Win11怎么退出高对比度模式_Win11取消反色显示快捷键【修复】 c# 服务器GC和工作站GC的区别和设置 Win10怎样设置闹钟贪睡时间 Win10闹钟贪睡时长设置【步骤】 Win11怎么关闭自动调节亮度 Win11禁用内容自适应亮度【设置】 php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】 Win11怎么设置任务栏透明_Windows11使用工具美化任务栏 Win10如何关闭安全中心所有通知 Win10禁用Windows Defender提醒【设置】 如何在Golang中引入测试模块_Golang测试包导入与使用实践 Win11怎么设置默认输入法 Win11固定中文输入法【步骤】 如何在Golang中定义接口_抽象方法和多态实现 Go 语言标准库为何不提供泛型 Contains 方法:设计哲学与类型系统约束 Win11任务栏怎么固定应用 Win11将软件图标固定到底部【步骤】 php中::能访问全局变量吗_全局作用域与类作用域区分【操作】 c# 在高并发下使用反射发射(Reflection.Emit)的性能 Windows如何拦截2345弹窗广告_Windows拦截2345弹窗方法【步骤】 Win7系统文件损坏如何修复_系统映像校验与替换步骤【修复专题】 GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息? Windows11怎样开启游戏模式_Windows11游戏模式开启攻略【方法】 Win11截图快捷键是什么_Win11自带截图工具使用技巧【汇总】 php怎么下载安装后设置错误日志_phpini log配置教程【汇总】 Win11怎么更改输入法顺序_Win11调整语言首选位置【设置】 如何使用Golang搭建本地API测试环境_快速验证接口功能
赣ICP备2024031479号