Подтвердить что ты не робот

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)

Почему?

4b9b3361

Ответ 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, содержащий элементы данной Коллекции.