LinkedHashMap存储重复键问题求助:Excel读取需保留重复条目
嗨,我完全明白你的困扰——你用LinkedHashMap<Integer, Map<String,String>>存储Excel读取的数据时,遇到重复Integer键就会覆盖旧条目,但你需要保留所有重复的记录。这其实是普通Map的固有特性:键必须唯一,所以重复键会自动替换之前的值。
你提到的MultiMap是Apache Commons Collections里的旧接口,现在已经被更易用的MultiValuedMap替代了,咱们用这个来解决问题,一步步来:
第一步:引入正确的依赖
你需要引入Apache Commons Collections4库。如果用Maven,在pom.xml里添加这段依赖:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.4</version> <!-- 用最新稳定版即可 --> </dependency>
如果是手动管理jar包,直接下载commons-collections4的jar文件加到项目classpath里就行。
第二步:替换Map类型为MultiValuedMap
把代码里的Map<Integer, Map<String,String>>换成MultiValuedMap<Integer, Map<String,String>>,具体用ArrayListValuedHashMap实现——它会为每个键维护一个ArrayList,专门用来存储多个值,完美满足你保留重复键条目的需求。
修改readXLSXFile方法里的temp变量声明:
// 原来的写法: // Map<Integer,Map<String,String>> temp = new LinkedHashMap<Integer,Map<String,String>>(); MultiValuedMap<Integer, Map<String,String>> temp = new ArrayListValuedHashMap<>();
第三步:调整put操作逻辑
原来的temp.put(...)会覆盖旧值,现在换成MultiValuedMap的put方法就行——它不会覆盖,而是把新值追加到对应键的列表里。另外注意你原来的names_Map是静态变量,容易导致数据污染,建议改成局部变量:
if (cell.getCellType() == cell.CELL_TYPE_STRING ) { String mainlabel= cell.getStringCellValue(); // 改成局部变量,避免后续修改影响已存入的数据 Map<String,String> names_Map = new HashMap<>(); names_Map.put(mainlabelholder, mainlabel); mainlabelholder = mainlabel; } else if (cell.getCellType() == cell.CELL_TYPE_NUMERIC) { // 存入MultiValuedMap,自动保留重复键 if (names_Map != null) { // 这里new一个新的HashMap,避免引用传递导致后续数据修改 temp.put((int) cell.getNumericCellValue(), new HashMap<>(names_Map)); } }
第四步:修改写入Excel的遍历逻辑
因为现在data_list里存的是MultiValuedMap,遍历方式要调整,需要遍历所有条目(包括重复键的每个值):
// 先修改data_list的泛型类型 static ArrayList<MultiValuedMap<Integer,Map<String,String>>> data_list = new ArrayList<>(); // 然后修改writeXLSXFile里的循环 for (int i = 0; i < data_list.size(); i++) { MultiValuedMap<Integer, Map<String,String>> multiMap = data_list.get(i); // 遍历所有条目,每个重复键的每个值都会被遍历到 for (Map.Entry<Integer, Map<String,String>> entry : multiMap.entries()) { Row tempRow = sheet.createRow(row++); // 用entry.getKey()和entry.getValue()获取键和对应的值 tempRow.createCell(0).setCellValue("Quota " + row + " " + fiscal_year); tempRow.createCell(1).setCellValue(entry.getKey().toString()); tempRow.createCell(2).setCellValue(day + "/" + row + "/" + year); Map<String,String> valueMap = entry.getValue(); tempRow.createCell(3).setCellValue(valueMap.values().iterator().next()); tempRow.createCell(4).setCellValue(valueMap.keySet().iterator().next()); // 其他单元格的逻辑按你的需求调整即可 // ... } }
核心修改后的代码片段
这里整理了关键部分的完整修改:
// 导入正确的包 import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; // 修改data_list的类型 static ArrayList<MultiValuedMap<Integer,Map<String,String>>> data_list = new ArrayList<>(); public static void readXLSXFile() throws IOException { String excelFilePath = "D:/xxxyy.xlsx"; FileInputStream inputStream = new FileInputStream(new File(excelFilePath)); XSSFWorkbook workbook = new XSSFWorkbook(inputStream); XSSFSheet firstSheet = workbook.getSheetAt(0); Iterator<Row> iterator = firstSheet.iterator(); String mainlabelholder = null; while (iterator.hasNext()) { Row nextRow = iterator.next(); Iterator cellIterator = nextRow.cellIterator(); MultiValuedMap<Integer, Map<String,String>> temp = new ArrayListValuedHashMap<>(); Map<String,String> names_Map = null; while (cellIterator.hasNext()) { XSSFCell cell = (XSSFCell) cellIterator.next(); if (cell.getCellType() == cell.CELL_TYPE_STRING ) { String mainlabel= cell.getStringCellValue(); names_Map = new HashMap<>(); names_Map.put(mainlabelholder, mainlabel); mainlabelholder = mainlabel; } else if (cell.getCellType() == cell.CELL_TYPE_NUMERIC) { if (names_Map != null) { temp.put((int) cell.getNumericCellValue(), new HashMap<>(names_Map)); } } } if (!temp.isEmpty()) data_list.add(temp); System.out.println("data List" + data_list); System.out.println("data List" + data_list.size()); System.out.println(""); } workbook.close(); inputStream.close(); }
这样修改后,你的代码就能完美保留所有重复的Integer键条目了。MultiValuedMap会为每个键维护一个值列表,每次put都会把新值追加进去,不会覆盖旧值。
内容的提问来源于stack exchange,提问作者vara

