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

Java HashMap存储学生成绩问题:复用List致数据覆盖的原因排查

问题原因与解决方案

你遇到的核心问题是Java中对象引用的传递机制:HashMap存储的不是ArrayList的副本,而是指向ArrayList对象的内存引用。你复用同一个marks对象,每次调用clear()和添加新元素时,修改的都是同一个内存地址里的列表实例,导致map中所有关联的学生都会指向这个被反复修改的列表,最终所有学生的成绩都会变成最后一次添加的内容。

代码运行过程拆解

  • 第一次put后,map里的"Rakesh"指向marks对象(内容为[12,10,15])
  • 调用marks.clear()后,该对象内容被清空,map中"Rakesh"对应的列表也同步为空
  • 第二次添加元素后,marks对象内容变为[9,8,15],此时map里的"Rakesh"和"Ashwin"都指向这个列表,打印时两个学生的成绩完全一致
  • 第三次重复操作后,三个学生的成绩都会变成最后一次添加的[7,11,8]

解决方案

方案1:每次创建新的ArrayList对象

不再复用同一个marks实例,处理每个学生时新建独立的ArrayList,确保每个学生对应唯一的列表对象:

HashMap<String, ArrayList<Integer>> map = new HashMap<>();

// 1st student detail
ArrayList<Integer> marks = new ArrayList<>();
marks.add(12);
marks.add(10);
marks.add(15);
map.put("Rakesh", marks);
System.out.println(map);

// 2nd student detail
marks = new ArrayList<>(); // 新建独立对象
marks.add(9);
marks.add(8);
marks.add(15);
map.put("Ashwin", marks);
System.out.println(map);

// 3rd student detail
marks = new ArrayList<>(); // 新建独立对象
marks.add(7);
marks.add(11);
marks.add(8);
map.put("Rahul", marks);
System.out.println(map);

方案2:存入map时创建ArrayList副本

如果一定要复用原marks对象,每次put到map时传入当前列表的副本,这样map存储的是独立的副本,后续修改原marks不会影响已存入的数据:

HashMap<String, ArrayList<Integer>> map = new HashMap<>();
ArrayList<Integer> marks = new ArrayList<>();

// 1st student detail
marks.add(12);
marks.add(10);
marks.add(15);
map.put("Rakesh", new ArrayList<>(marks)); // 存入副本
System.out.println(map);

marks.clear();

// 2nd student detail
marks.add(9);
marks.add(8);
marks.add(15);
map.put("Ashwin", new ArrayList<>(marks)); // 存入副本
System.out.println(map);

marks.clear();

// 3rd student detail
marks.add(7);
marks.add(11);
marks.add(8);
map.put("Rahul", new ArrayList<>(marks)); // 存入副本
System.out.println(map);

扩展:实现成绩排名前三的需求

解决存储问题后,可通过计算总成绩并排序来获取排名前三的学生:

// 计算总成绩并按倒序排序,取前3名
List<Map.Entry<String, ArrayList<Integer>>> sortedStudents = map.entrySet()
        .stream()
        .sorted((e1, e2) -> {
            int sum1 = e1.getValue().stream().mapToInt(Integer::intValue).sum();
            int sum2 = e2.getValue().stream().mapToInt(Integer::intValue).sum();
            return Integer.compare(sum2, sum1); // 倒序排列
        })
        .limit(3)
        .toList();

// 输出结果
System.out.println("成绩排名前三的学生:");
sortedStudents.forEach(entry -> {
    int total = entry.getValue().stream().mapToInt(Integer::intValue).sum();
    System.out.println(entry.getKey() + " - 总成绩:" + total);
});

内容的提问来源于stack exchange,提问作者Rakesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:27:26