2014-02-20 2 views
0
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; 
} 

Может ли кто-нибудь сказать мне, что случилось с этим?Исключение в теме "main" java.lang.ArrayIndexOutOfBoundsException: 6

Я не могу понять, почему я получаю сообщение об ошибке через несколько часов: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6 Поскольку два набора, поставляемые в качестве аргументов, могут иметь разный домен max; результирующий союз должен иметь какой бы то ни было из этих двух доменов max больше, поэтому я использую Math.max.

Любая помощь будет оценена по достоинству.

+4

Как вы думаете, а это значит?Как только вы это знаете, вы можете работать назад, чтобы выяснить источник. –

+1

Представьте себе, s1.dMax равно 10 и s2.dMax равно 20. Так что, если вы повторяете до Max (10,20), что равно 20, что произойдет с s1.set? – exception1

+0

Вставьте вызовы в System.out.println, чтобы распечатать ваши значения, работая в обратном направлении от точки исключения. (Или используйте отладчик.) –

ответ

0

Проблема возникает, когда 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! По мере того как цикл ошибочно пытается получить доступ к элементам 7 через 12 (индексы 6 по 11) из s1, он бросает ArrayIndexOutOfBoundsError.

Чтобы это исправить, необходимо использовать минимальной длину двух множеств в обеих линиях, где вы используете максимум. Таким образом, вы будете принимать в союз:

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 «S для каждого недостающего элемента в более короткий набор, в результате чего накидной существа:

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 сам по себе.

+0

Ах, я вижу! Теперь имеешь смысл! Спасибо, что поняли мне! Наверное, глупый вопрос, но не использовать min пропустить некоторые элементы для создания союза? Как я думал, результирующий союз должен иметь любой из этих двух доменов max больше. То есть 's1: {2 4}' 's2: {4 5 6 7 9}' Только дает мне {2 4 5} – ollie283

+0

@ user3334639 См. Мое редактирование. Я думаю, это может быть то, что вы ищете. – ApproachingDarknessFish

+0

Я вижу, что ваш код делает с вашим объяснением, но я не думал, что вы можете применить || оператор для boolean? – ollie283

0

Это:

dMax = domainMax + 1; 

должно быть:

dMax = domainMax; 

Или просто использовать set.length.

0

Ваш заход от 0 до максимального размера s1 и s2. Но так как (в той ситуации, которая кидает ошибку), один из ваших IntegerSet с меньше, то для контура проходит мимо размера меньшего IntegerSet при получении всех boolean с от большего IntegerSet

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

    union.set[i] = (s1.set[i] || s2.set[i]); 
} 

If размер одного набора меньше максимального, тогда вы получите 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 

в вашей для цикла, вы собираетесь итерацию от 0 до 4. Когда происходит следующее:

i = 3 
s1.set[i] = s1.set[3] //IndexOutOfBoundsException because the size of s1.set is 3. 

У вас есть несколько вариантов, как вы можете исправить это:

  • Вы можете добавить проверку в вашем для цикла, чтобы убедиться, что вы не
    собирается получить IndexOutOfBoundsException для вашего меньше
    IntegerSet и просто установить индекс в union к boolean стоимости вашего большего набора.
  • Вы можете разместить свой меньший IntegerSet в зависимости от того, что вы хотите для соединения .
  • Используйте min размер двух IntegerSet с, если вы хотите игнорировать дополнительные boolean с (судя по тому, что вы сделали союз установить размер макс, я думаю, что это не так)

Side Примечание: Вам также не нужно, чтобы добавить +1 к переменной dMax при создании unionIntegerSet. Это приведет к тому, что у вас будет дополнительный индекс, который вам не нужен, и может вызвать проблемы позже.

+0

Но мне не нужно иметь domianMax + 1, чтобы разрешить 0? Так что, если я создам массив [5], я получу {0 1 2 3 4} – ollie283

+0

Не уверен, что вы имеете в виду. int [] array = new int [5]; initialsies массив со всеми '0' является верю. Таким образом, это будет {0, 0, 0, 0, 0}. Но у вас будет 5 причин. Значение, которое передается в ваш конструктор 'IntegerSet', является размером другого' IntegerSet', поэтому вам не следует пропускать никаких указаний. – mdewitt

0

Вы используете dMax как число boolean array элементов в одном месте и в качестве максимального (недопустимого) домена при создании нового набора union. (Это заставляет вас сделать union 1 элемент слишком велик.)

Несколько вещей, которые необходимо учитывать при переписать код:

  1. Предполагая domainMax предполагающее множество целых чисел из [0, domainMax], не определит логический массив с domainMax+1 элементами (не заморачиваться с переменной Dmax, вы можете получить эту информацию, проверяя set.length
  2. в функции «union», обязательно обрабатывают случай, когда один или оба входных IntegerSet с равно нулю
  3. Используйте protected set, чтобы убедиться, что внутреннее представление IntegerSet неизвестно или доступно за пределами вашего класса.
  4. Когда вы выполняете объединение двух ненулевых IntegerSet s, выполняйте операцию или операцию (||) для случая, когда оба множества имеют значения; то для «большего» набора просто скопируйте оставшиеся предметы.
Смежные вопросы