Java中ArrayList<ArrayList<Integer>>使用异常排查
问题分析与修复方案
让我看看你的代码,你现在遇到的输出混乱和数据丢失问题,主要源于两个关键错误:
1. 错误使用add()而非set()导致元素位置错乱
你的构造方法已经初始化了gpond,包含V个ArrayList实例。但在VPond方法中,你用了gpond.add(v, temp)——这个方法的作用是在索引v的位置插入新元素,会把原索引v及之后的所有元素向后“挤”一位。这会造成两个问题:
gpond的长度会超过V,但你的printGraph方法只遍历前V个元素,后续的初始空列表被忽略。- 你添加的新列表会打乱原有位置,导致最终输出的节点顺序完全不符合预期。
2. 每次创建新列表覆盖原有边数据
你期望同一个节点可以有多条边(比如节点0同时指向1和2),但当前VPond的逻辑是:创建一个全新的temp列表,只设置当前w位置的值,然后插入到gpond中。这会直接覆盖节点v之前的所有边数据——比如你先添加0→1,再添加0→2,前者就会被后者完全覆盖,自然看不到预期的两条边。
修复步骤
第一步:修正构造方法,初始化每个节点的列表为带V个null的容器
原来的构造方法里,每个节点的ArrayList只是设置了初始容量,并没有实际元素。我们需要给每个节点的列表初始化V个null,这样后续可以直接修改对应位置的值:
GrPond(int v) { V = v; gpond = new ArrayList<>(); for (int i = 0; i < V; i++) { ArrayList<Integer> nodeEdges = new ArrayList<>(V); // 给每个节点的列表初始化V个null元素 for (int j = 0; j < V; j++) { nodeEdges.add(null); } gpond.add(nodeEdges); } }
第二步:修改VPond方法,直接修改原有列表的对应位置
不需要再创建新的temp列表,直接获取节点v对应的列表,然后设置w位置的值即可,这样不会覆盖之前的边数据:
void VPond(int v, int w, int val) { // 直接操作节点v的原有列表,设置w位置的值 gpond.get(v).set(w, val); }
第三步:(可选)优化printGraph方法
你的打印逻辑没问题,但可以简化一下,让代码更清晰:
void printGraph() { for (int i = 0; i < V; i++) { System.out.println("node " + i); ArrayList<Integer> nodeEdges = gpond.get(i); for (int j = 0; j < V; j++) { Integer val = nodeEdges.get(j); if (val != null) { System.out.println("[" + i + "]-> [" + j + "] | val: " + val); } } } System.out.println("\n测试输出:"); for (ArrayList<Integer> e : gpond) { System.out.println("e: " + e); } }
测试结果
当你运行以下代码:
public static void main(String[] args) { GrPond graph = new GrPond(3); graph.VPond(0, 1, 2); graph.VPond(0, 2, 1); graph.VPond(1, 0, 1); graph.printGraph(); }
会得到和你预期一致的输出:
node 0 [0]->[1] | val: 2 [0]->[2] | val: 1 node 1 [1]->[0] | val: 1 node 2 测试输出: e: [null, 2, 1] e: [1, null, null] e: [null, null, null]
内容的提问来源于stack exchange,提问作者Izanami
相关产品推荐
相关产品推荐

