[英]Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 7
[英]Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 6
public class IntegerSet {
int dMax;
boolean[] set;
public IntegerSet(int domainMax) {
dMax = domainMax + 1;
set = new boolean[dMax];
}
...some methods...
public static IntegerSet union(IntegerSet s1, IntegerSet s2) {
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
union.set[i] = (s1.set[i] || s2.set[i]);
}
return union;
}
谁能告诉我这怎么了?
我不明白为什么下班后会收到错误消息: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
由于作为参数提供的两个集合可能具有不同的域最大值; 结果得到的联合应该具有这两个域max中的最大值,因此我为什么要使用Math.max。
任何帮助,将不胜感激。
这个:
dMax = domainMax + 1;
应该:
dMax = domainMax;
或者只是使用set.length
。
您的for循环从0
到s1
和s2
的最大大小。 但是因为(在引发错误的情况下)您的一个IntegerSet
较小,所以当从较大的IntegerSet
检索所有boolean
s时,for循环超过了较小的IntegerSet
的大小。
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
union.set[i] = (s1.set[i] || s2.set[i]);
}
如果一组的大小小于最大值,那么您将获得IndexOutOfBoundsException
。
例:
假设您具有以下条件:
s1 = {0, 1, 1, 0, 1}
s2 = {0, 0, 0}
s1.dMax = 5, so s1.set has a size of 5
s2.dMax = 3, so s2.set has a size of 3
在for循环中,您将从0迭代到4。发生以下情况:
i = 3
s1.set[i] = s1.set[3] //IndexOutOfBoundsException because the size of s1.set is 3.
您有几种方法可以解决此问题:
IndexOutOfBoundsException
IntegerSet
并将索引union
设置为较大集合的boolean
值。 IntegerSet
具体取决于您希望空白索引的并集是什么。 boolean
请使用两个IntegerSet
的min
大小(从您使并集设置了最大大小的事实来看,我猜并非如此) 注意:创建union
IntegerSet
时,也不需要将+1
添加到dMax
变量。 这将导致您拥有不需要的额外索引,以后可能会导致问题。
当s1
和s2
具有不同的长度时会出现问题。 这些行是有缺陷的:
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
考虑一下两组不等长的样子:(使用1和0代替true
和false
)
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
您已将循环编程为从0迭代到两组的最大长度,在上面的示例中为12(这意味着循环将使用的最后一个值为11)。 但是s1
只有6个元素长,它的最后一个有效索引是5! 当循环错误地尝试访问s1
元素7到12(索引6到11)时,它抛出ArrayIndexOutOfBoundsException.
要解决此问题,您应该在使用最大值的两行中使用两组最小长度。 这样,您将参加工会:
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1} length = min(6, 12) = 6
代替
s1: {0 1 0 0 1 1}! ! ! ! ! ! length = 6; no elements 7 through 12!
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1 ! ! ! ! ! !} length = max(6, 12) = 12 -> errors
这将s2
的后面部分排除在并集之外,因为s1
中没有相应的元素可以执行布尔||
用。 但是,您也可以执行以下操作:
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
if (s2.set.length > s1.set.length)
{
union.set[i] = s2.set[i] || (i < s1.set.length ? s1.set[i] : false);
}
else
{
union.set[i] = s1.set[i] || (i < s2.set.length ? s2.set[i] : false);
}
}
这将对较短集中的每个缺少的元素使用false
,导致合并为:
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1 1 0 1 1 0 1} length = max(6, 12) = 12
所有条目都是从较长的集中复制而来,因为anything || false
anything || false
本身。
您将dMax
用作一处boolean array
元素的数量,并将其用作创建新union
集时的域最大值(错误)。 (这会使您使union
1元素太大。)
重写代码时要考虑的几件事:
domainMax
隐含[0,domainMax]中的一组整数,请使用domainMax+1
元素定义一个布尔数组(不要理会dMax变量,您可以通过检查set.length
来获取该信息。 union
”函数中,请确保处理其中一个或两个输入IntegerSet
均为null的情况 protected set
来确保IntegerSet
的内部表示在您的类之外是未知的或无法访问的 IntegerSet
的并集时,仅当两个集合都具有值时才执行or操作(||);否则,请执行。 然后对于“更大”的集,只需复制其余项目即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.