繁体   English   中英

线程“主”中的异常java.lang.ArrayIndexOutOfBoundsException:6

[英]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循环从0s1s2的最大大小。 但是因为(在引发错误的情况下)您的一个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. 

您有几种方法可以解决此问题:

  • 您可以在for循环中添加检查,以确保您没有
    将为您的较小对象获取IndexOutOfBoundsException
    IntegerSet并将索引union设置为较大集合的boolean值。
  • 您可以填充空白的IntegerSet具体取决于您希望空白索引的并集是什么。
  • 如果要忽略多余的boolean请使用两个IntegerSetmin大小(从您使并集设置了最大大小的事实来看,我猜并非如此)

注意:创建union IntegerSet时,也不需要将+1添加到dMax变量。 这将导致您拥有不需要的额外索引,以后可能会导致问题。

s1s2具有不同的长度时会出现问题。 这些行是有缺陷的:

IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {

考虑一下两组不等长的样子:(使用1和0代替truefalse

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元素太大。)

重写代码时要考虑的几件事:

  1. 假设domainMax隐含[0,domainMax]中的一组整数,请使用domainMax+1元素定义一个布尔数组(不要理会dMax变量,您可以通过检查set.length来获取该信息。
  2. 在“ union ”函数中,请确保处理其中一个或两个输入IntegerSet均为null的情况
  3. 使用protected set来确保IntegerSet的内部表示在您的类之外是未知的或无法访问的
  4. 当执行两个非null IntegerSet的并集时,仅当两个集合都具有值时才执行or操作(||);否则,请执行。 然后对于“更大”的集,只需复制其余项目即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM