Java.lang.IndexOutOfBoundsException: источник не вписывается в dest
В следующем коде:
static void findSubsets (ArrayList<Integer> numbers, int amount, int index)
{
ArrayList <Integer> numbersCopy = new ArrayList<Integer>(numbers.size());
Collections.copy(numbersCopy, numbers);
}
Я получаю сообщение об ошибке:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Source does not fit in dest
at java.util.Collections.copy(Collections.java:548)
at backtracking2.Main.findSubsets(Main.java:61)
Почему?
Ответы
Ответ 1
Емкость не равна размеру. Параметр размера, который вы передаете, просто выделяет достаточно памяти для размера. Он фактически не определяет элементы. На самом деле это глупое требование Collections.copy
, но оно тем не менее.
Ключевая часть Collections.copy
JavaDocs:
Список адресатов должен быть не меньше, чем список источников. Если он длиннее, остальные элементы в списке адресатов не затрагиваются.
Вы должны просто передать конструктор List
в конструктор ArrayList
, чтобы скопировать все List
, чтобы избежать проблемы вообще.
Ответ 2
Это очень хороший вопрос, и это почти наверняка связано с тем, что установка емкости коллекций не обязательно выделяет базовые объекты, но почему вы делаете это так, когда можете просто:
ArrayList <Integer> numbersCopy = new ArrayList<Integer>(numbers);
Ответ 3
Конструктор ArrayList(Collection<? extends E> c)
скопирует все элементы из c
во вновь созданный экземпляр, скопировав numbers
в numbersCopy
. Это то же самое, что и numbersCopy.addAll(numbers)
, что вам действительно нужно.
Имеет смысл, что Collection.copy
требует, чтобы массив dest
был достаточно большим, чтобы удерживать все элементы из массива source
. Аналогичной аналогией является функция C memcpy
и т.п.
Ответ 4
При создании ArrayList
для копирования другого ArrayList
с использованием метода Collections.copy()
, мы должны убедиться, что пункт назначения List
содержит то же количество значений (а не только тот же размер), что и источник List
. Например, если источник ArrayList
имеет значения [Red, Blue, Green], тогда пункт назначения ArrayList
также должен содержать такое же количество элементов, как [Orange, Yellow, Blue]. Если мы создаем ArrayList
с таким же размером что из источника ArrayList
, это даст исключение OutOfBounds
.
Ответ 5
В Ява 8 +
List<Integer> numbersCopy = numbers.stream().collect(Collectors.toList());
Это проще в Java 10+
List<Integer> numbersCopy = List.copyOf(numbers);
Список .copyOf()
возвращает список unmodifiable
, содержащий элементы данной Коллекции.