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

Java HashMap.get返回多值异常:图反转方法错误排查

问题根源分析

你遇到的这个问题核心原因是同一个ArrayList实例被绑定到了HashMap的多个不同键上,导致当你向其中一个键对应的列表添加元素时,其他共享该实例的键的列表也会同步变化。

看你的reverseGraph方法代码片段:

for(Integer x:g.getVertices()) {
    ArrayList<Integer> edges = new ArrayList<Integer>();
    edges.add(x);
    // ...
    for(Integer y:g.getAdjList().get(x)) {
        // ...
        if(revAdjList.containsKey(y)) {
            revAdjList.get(y).add(x);
        } else {
            revAdjList.put(y, edges); // 这里就是问题所在!
        }
    }
}

在每个外层循环(遍历x)中,你只创建了一个edges列表。当处理当前x对应的多个y时,如果这些y都不在revAdjList里,你会把同一个edges实例依次绑定到这些y键上。比如某个x对应的y=5和y=6都不存在于revAdjList,那么键5和键6都会指向同一个ArrayList对象。之后当你调用revAdjList.get(6).add(3)时,因为键5和6的列表是同一个实例,所以键5的列表也会多出一个3,这就是你日志里看到的异常现象。

修复方案

只需要在else分支中,为每个新的y创建一个全新的ArrayList实例,而不是复用当前x循环里的edges列表。修改代码如下:

if(revAdjList.containsKey(y)) {
    revAdjList.get(y).add(x);
} else {
    // 为每个y创建独立的ArrayList,避免实例共享
    ArrayList<Integer> newEdges = new ArrayList<>();
    newEdges.add(x);
    revAdjList.put(y, newEdges);
    // 如果你用Java 9及以上版本,也可以用简化写法:
    // revAdjList.put(y, new ArrayList<>(List.of(x)));
}
额外优化建议
  1. 调试代码清理:你代码里有一行硬编码的revAdjList.get(5),这是调试时的残留,建议改成revAdjList.get(y),不然日志只会打印键5的内容,影响调试准确性。

  2. 顶点列表优化:反转图的顶点集合和原图完全一致,不需要通过遍历邻接边来逐个添加revVertices,直接复制原图的顶点列表即可:

ArrayList<Integer> revVertices = new ArrayList<>(g.getVertices());

这样可以避免漏掉原图中的孤立节点(那些没有出边的顶点)。

验证修复效果

修改后,每个键对应的ArrayList都是独立的实例,向一个键的列表添加元素时,不会影响其他键的列表。你可以重新运行代码,观察日志,就能看到键5和键6的列表不再同步变化了。

内容的提问来源于stack exchange,提问作者Cosmin Şoavă

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:27:11