为什么我的 ArrayList 会出现 ArrayIndexOutOfBoundsException

Why do I get an ArrayIndexOutOfBoundsException For My ArrayList

我看不出我的代码有什么问题:-

import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {

       int[] A = new int[] {2, 1, 1, 2, 3, 1}; 
       ArrayList<Integer> foundNumbers = new ArrayList<>();
        int distinct = 0;

        for(int i = 0; i < A.length-1; i++) {
            if(foundNumbers.get(i-1) == null) {

                foundNumbers.set((i-1), A[i]);
                distinct++;
            }


    }
        System.out.println(distinct);
}    
}

我想检查数组元素 i 的值是否已经分配给 ArrayList 元素 i-1,然后递增 distinct 变量并打印数组中有多少个不同的值。

这是我将 i 的值更改为 1 时的异常:-

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:604)
    at java.util.ArrayList.get(ArrayList.java:382)
    at tdd.Main.main(Main.java:19)
for(int i = 0; i < A.length-1; i++) {
    if(foundNumbers.get(i-1) == null) {

在该循环的 第一次 迭代中,i 将被设置为零,因此第二行正在执行 .get(-1).

列表完全为空。您没有在其中放入任何内容,但您正在尝试使用 foundNumbers.get 调用从中读取元素,因此任何索引都将超出范围。

要将 A 中的唯一元素添加到列表中,getset 只是调用错误的列表方法,请使用 containsadd 如果那是你想要做的:

for (int x : A) {
    if (!foundNumbers.contains(x))
        foundNumbers.add(x);
}

这里以更详细的方式编写了与上面相同的逻辑,可能更容易理解所涉及的内容:

for (int i = 0; i < A.length; i++) {
    boolean found = false;
    for (int j = 0; j < foundNumbers.size(); j++) {
        if (A[i] == foundNumbers.get(j)) {
            found = true;
            break;
        }
    }
    if (!found) {
        foundNumbers.add(A[i]);
    }
}

您不需要单独的 distinct 变量,因为它只是 foundNumbers.size().


虽然这可行,但如果元素数量很大,List 对消除重复项的效率不是很高,因为每个 contains 调用都需要对列表的内容进行另一个循环。 Set 自动防止重复并在内部以高效的方式构建其内容:

Set<Integer> distinct = new TreeSet<>();
for (int x : A) distinct.add(x);
System.out.println(distinct); // [1, 2, 3]

存在多个问题:

  • 当 i 为 0 时,您尝试获取无效的第 i-1=-1 个元素
  • 即使你修复了这个问题,因为列表中没有元素,你仍然会得到 IndexOutOfBoundsException,因为你还没有存储任何元素并且你的列表是空的。

你的循环应该是:

for (int i = 0; i < A.length - 1; i++) {
        if (foundNumbers.size() > i && foundNumbers.get(i) == null) {//or better you use contains method of list like foundNumbers.contains(someNumber);
            foundNumbers.add(A[i]);
            distinct++;
        }
}