为什么我的 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
中的唯一元素添加到列表中,get
和 set
只是调用错误的列表方法,请使用 contains
和 add
如果那是你想要做的:
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++;
}
}
我看不出我的代码有什么问题:-
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
中的唯一元素添加到列表中,get
和 set
只是调用错误的列表方法,请使用 contains
和 add
如果那是你想要做的:
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++;
}
}