【问题标题】:ArrayList index out of bound but HashSet has no issueArrayList 索引超出范围但 HashSet 没有问题
【发布时间】:2020-11-30 12:46:36
【问题描述】:

我有一个简单的 Graph 类,它使用列表数组跟踪哪些元素相互链接。

从列表中删除元素时,我收到IndexOutOfBoundsException。我的错误在代码下方。

但如果我将集合从ArrayList<Integer> 更改为HashSet<Integer>,它就可以正常工作。

为什么Arraylist<Integer> 类型在这里不起作用,而HastSet<Integer> 起作用?

以及移除这些集合元素的内部机制是什么?

class Graph {
    int v;

    ArrayList<Integer>[] connections;

    Graph(int v) {
        this.v = v;
        connections = new ArrayList[v];
        for (int i = 0; i < v; i++) {
            connections[i] = new ArrayList<>();
        }
    }

    void addConnection(int u, int v) {
        connections[u].add(v);
        connections[v].add(u);
    }

    void removeConnection(int u, int v) {
        connections[u].remove(v);
        connections[v].remove(u);
    }
}

class Main{
  
    public List<List<Integer>> criticalConnections(int n, List<List<Integer>> connections) {
        List<List<Integer>> result = new ArrayList<>();
        Graph graph = new Graph(n);
     
        for (List<Integer> connection : connections) {
            graph.addConnection(connection.get(0), 
            connection.get(1));

    for (List<Integer> connection : connections) {
         graph.removeConnection(connection.get(0), 
         connection.get(1));
         graph.addConnection(connection.get(0), 
         connection.get(1));
    }
}

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 2 out of bounds for length 2
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:372)

【问题讨论】:

  • 请包含完整的堆栈跟踪并突出显示发生异常的行。 --- "connections = new ArrayList[v];" - The usage of raw types is highly discouraged.
  • 另外,请发帖minimal reproducible example。您发布的代码不完整。
  • 我在以下行收到错误--graph.removeConnection(connection.get(0),connection.get(1));
  • 堆栈跟踪--java.lang.IndexOutOfBoundsException:索引 2 在第 64 行超出长度 2 的范围,java.base/jdk.internal.util.Preconditions.outOfBounds 在第 70 行,java.base /jdk.internal.util.Preconditions.outOfBoundsCheckIndex 在第 248 行,java.base/jdk.internal.util.Preconditions.checkIndex 在第 373 行,java.base/java.util.Objects.checkIndex 在第 502 行,java.base/ java.util.ArrayList.remove 在第 105 行,Graph.removeConnection
  • edit您的问题并将这些信息包含在问题中,而不是在 cmets 中。

标签: java arrays arraylist hash collections


【解决方案1】:

你的问题是方法签名:

void removeConnection(int u, int v) { // <-- These should be Integer, not int
    connections[u].remove(v);
    connections[v].remove(u);
}

原因是List两个删除方法:

  1. remove(int index) 删除索引处的元素 index
  2. remove(Object object) 查找并删除 object

您正在调用版本 1,但您想要版本 2。

Set 但是没有 remove(int index) 方法,因此 java auto-boxesint 转换为 Integer 并且该方法按预期工作(正如您所发现的那样)。

通过将方法签名更改为

void removeConnection(Integer u, Integer v)

调用了正确版本的remove()。如果将int 传递给该方法,它将自动装箱为Integer,因此您对该方法的使用无需更改。


这是一种极端情况;它仅在集合类型为 Integer 时发生,当正在尝试自动装箱时。但是,由于令人困惑,即使仔细调试也很难理解,因此这种特殊情况值得牢记在心。

【讨论】:

    猜你喜欢
    • 2022-01-13
    • 1970-01-01
    • 2021-12-10
    • 2019-03-25
    • 2017-07-30
    • 2021-07-11
    • 2020-02-13
    • 1970-01-01
    相关资源
    最近更新 更多