java读取excel文件内容并输出 java读取excel图片
在Java中处理Excel数据时,若需将每行转换为Map存储,并要求Map内部的列顺序与Excel原文保持一致,传统的HashMap无法满足此需求,因为它不能保证元素的插入顺序。本文将详细介绍如何利用LinkedHashMap或TreeMa为了解决这个问题,保证读取的Excel列顺序能够准确保留,尤其适用于后续需要按顺序写回Excel的场景。理解Map的顺序特性
在Java集合框架中,Map接口有多种实现类,它们在键值对的存储和检索方式上有所不同,特别是在顺序性方面:HashMap:这是最常用的Map实现,它提供了O(1)的平均时间复杂度进行插入、删除和查找操作。然而,HashMap不保证任何迭代顺序,其元素的顺序可能随时间变化,甚至在相同的元素集上,不同的JVM实现或运行环境都可能产生不同的。因此,如果需要保持顺序插入,HashMap不是一个合适的选择。LinkedHashMap: LinkedHashMap继承自HashMap,并额外维护了一个集合链表来记录元素的插入顺序。这意味着当你浏览LinkedHashMap时,元素的顺序将与它们被插入时的顺序完全一致。这对于需要保留原始数据顺序的场景(如Excel列顺序)非常有用。TreeMap: TreeMap实现了SortedMap接口,它根据按键的自然顺序(对于字符串是字母顺序)或者在创建TreeMap时提供的比较器进行排序。虽然TreeMap也提供了排序规则,但它的顺序是基于按键的排序解决规则,而不是插入顺序。因此,如果你的目标是保持Excel的原始列顺序(即从左到右的物理顺序),LinkedHashMap通常是更直接和合适的选择。方案:使用LinkedHashMap保持列顺序
为了保证从Excel读取数据并存储为Listgt;时候能够保持原始的列顺序,需要我们将存储每行数据的HashMap替换为LinkedHashMap。LinkedHashMap会按照键值对被插入的顺序来维护内部结构,从而完美地解决了列顺序不一致的问题。
以下是修改后的Java示例:import代码org.apache.poi.ss.usermodel.*;导入java.util.*;导入java.util.stream.Collectors;公共类ExcelReaderWithOrder { /** * 从Excel工作表中读取数据,并以Listlt;Maplt;String, Stringgt;gt;的形式返回,*其中Map内部的键值对顺序与Excel列的物理顺序保持一致。
* * @paramsheet要读取的Excel工作表对象 * @return 包含Excel数据的List,每个Map代表一行,键为列名,值为单元格内容 */ public static Listlt;Maplt;String, Stringgt;gt; readExcelSheet(Sheetsheet) { Iteratorlt;Rowgt; rows =sheet.iterator(); // 如果工作表为空,返回空列表 if (!rows.hasNext()) { return Collections.emptyList(); } // 读取第一行作为表头,提取列名 Row header = rows.next();Listlt;Stringgt;keys = new ArrayListlt;gt;(); for (Cell cell : header) { String value = cell.getStringCellValue(); // 只需添加非空的列名,遇到空列名则停止,之后后续无有效列 if (!value.isEmpty()) { keys.add(value); } else { break; } } Listlt;Maplt;String, Stringgt;gt; 结果 = new ArrayListlt;gt;(); // 遍历剩余的行数据 while (rows.hasNext()) { Row row = rows.next(); // 重点:使用LinkedHashMap来保证列的插入顺序 Maplt;String, Stringgt; rowMap = new LinkedHashMaplt;gt;(); // 遍历表头定义的列,填充当前行的数据 for (int i = 0; i lt;keys.size(); i) { //获取单元格,如果单元格不则创建为空白单元格 Cell cell = row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); String value; // 将单元格内容转换为字符串 value = cell.toString(); rowMap.put(keys.get(i), value); } // 只需添加非空行到结果列表 // 判断
条件:如果所有值都不是空字符串,则认为该行有效 if (!rowMap.values().stream().allMatch(String::isEmpty)) { result.add(rowMap); } } return result; } public static void main(String[] args) { // 示例含义:想象你有一个Workbook对象 // Workbook workbook = new XSSFWorkbook(quot;your_excel_file.xlsxquot;); // Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表 // Listlt;Maplt;String, Stringgt;gt; data = readExcelSheet(sheet); // System.out.println(data); // 模拟一个Sheet对象和数据进行测试 // 实际应用中需要引入Apache POI库并加载真实的Excel文件 // 这里演示演示LinkedHashMap效果 System.out.println(quot;--- 模拟Excel数据读取 ---quot;); //模拟表头Listlt;Stringgt;mockHeaders = Arrays.asList(“第1列”;,“第2列”;); // 模拟数据行 Listlt;Listlt;Stringgt;gt;mockRows = new ArrayListlt;gt;();mockRows.add(Arrays.asList(“;value1”;,“;value2”;));mockRows.add(Arrays.asList(“;value3”;, quot;value4quot;)); // 手动构建预期结果,以验证LinkedHashMap的顺序 Listlt;Maplt;String, Stringgt;gt;预期输出 = new ArrayListlt;gt;(); Maplt;String, Stringgt; row1 = new LinkedHashMaplt;gt;(); row1.put(quot;column 1quot;, quot;value1quot;); row1.put(quot;column2quot;, ”;value2”;);预期输出.add(row1); Maplt;String, Stringgt; row2 = new LinkedHashMaplt;gt;();
row2.put(“第1列”;,“value3”;);row2.put(“column2”;,“value4”;);expectedOutput.add(row2);System.out.println(";预期输出(LinkedHashMap):";);expectedOutput.forEach(map -gt;{map.forEach((key,value)-gt;System.out.println("; quot; key quot; -gt; quot; value))); }); System.out.println(quot;\n实际模拟代码运行效果(如果使用LinkedHashMap,效果将与预期一致):quot;); // 在实际的readExcelSheet方法中,如果将HashMap改为LinkedHashMap, // 那么输出的Map内部顺序将是quot;column 1quot;, quot;column2quot; //这里的主要方法只是演示,readExcelSheet真实需要的POI Sheet对象 }}登录后复制
代码解析:
立即学习“Java免费学习笔记(深入)”;
核心的税务要求将Map rowMap = new HashMap();替换为Map rowMap = new LinkedHashMap();。通过这个简单的更改,rowMap将自动维护按键值对的插入顺序,即按照Excel表头中列的从左到右顺序。注意事项依赖管理:另外使用代码了Apache POI库来处理Excel文件。在实际中,您需要确保项目中已正确引入Apache POI的依赖(例如,在Maven项目中添加poi和poi-ooxml依赖)。单元格类型处理: 示例代码中使用了cell.toString()来获取单元格的值。这把所有单元格内容统一转换为字符串。在实际应用中,如果Excel单元格包含数字、日期、布尔值等不同类型的数据,你可能需要根据cell.getCellType()来判断单元格类型,并使用更具体的方法(如getNumericCellValue()、getDateCellValue()等)来获取数据,识别数据错误或丢失。列空名处理:代码中在读取表头时,如果遇到空字符串的列名,会立即停止读取后续列。这相当于Excel表头是连续的,且空列名意味着没有更多的有效列。根据实际的Excel文件结构,可能需要调整这个逻辑。空行过滤:代码中通过!rowMap.values().stream().allMatch(String::isEmpty)来过滤掉所有单元格都为空的行。这样有助于清理数据,避免处理多余空白的行。错误处理:在实际的生产环境中,需要考虑更多的错误处理机制,例如文件不存在、文件格式错误、权限问题等。
总结
当从Excel文件中读取数据并希望保留原始的列顺序时,LinkedHashMap是Java中一个非常有效的解决方案。它通过维护插入顺序的特性,保证了Map中键值对的顺序与Excel工作表中的列顺序保持一致。对于后续的数据处理、数据校验或将数据写回Excel等操作都至关重要。了解不同Map实现类的特性,并根据具体需求选择合适的工具,是高效和健壮编程的关键。
以上就是Java中读取Excel数据并保持列顺序:使用LinkedHashMap的内容详细,更多请关注乐哥常识网其他相关文章!