You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LinkedHashMap存储重复键问题求助:Excel读取需保留重复条目

解决重复Integer键存储问题:用MultiValuedMap替代LinkedHashMap

嗨,我完全明白你的困扰——你用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:25:44