簡體   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