[英]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.