Java IndexOutOfBoundsException „Източникът не се побира в дестинация“

1. Общ преглед

В Java, копирането на списък понякога може да доведе до IndexOutOfBoundsException: „Източникът не се побира в дестинация“. В този кратък урок ще разгледаме защо получаваме тази грешка при използване на метода Collections.copy и как тя може да бъде решена. Ще разгледаме и алтернативи на Collections.copy, за да направим копие на списъка.

2. Възпроизвеждане на проблема

Нека започнем с метод за създаване на копие на Списък, използвайки метода Collections.copy :

static List copyList(List source) { List destination = new ArrayList(source.size()); Collections.copy(destination, source); return destination; }

Тук методът copyList създава нов списък с първоначален капацитет, равен на размера на списъка източник. След това се опитва да копира елементите от списъка с източници в списъка с местоназначения:

List source = Arrays.asList(1, 2, 3, 4, 5); List copy = copyList(source);

След като обаче извикаме метода copyList , той хвърля изключение java.lang.IndexOutOfBoundsException: Източникът не се побира в dest .

3. Причина за изключението

Нека се опитаме да разберем какво се обърка. Според документацията за метода Collections.copy :

Целевият списък трябва да бъде поне толкова дълъг, колкото списъка източник. Ако е по-дълго, останалите елементи в списъка с дестинации не се влияят.

В нашия пример създадохме нов Списък, използвайки конструктор с първоначален капацитет, равен на размера на списъка източник. Той просто разпределя достатъчно памет и всъщност не дефинира елементи. Размерът на новия списък остава нула, тъй като капацитетът и размерът са различни атрибути на списъка .

Следователно, когато методът Collections.copy се опитва да копира списъка с източници в целевия списък, той хвърля java.lang.IndexOutOfBoundsException.

4. Решения

4.1. Колекции.копия

Нека да разгледаме работещ пример за копиране на списък в друг списък , използвайки метода Collections.copy :

List destination = Arrays.asList(1, 2, 3, 4, 5); List source = Arrays.asList(11, 22, 33); Collections.copy(destination, source);

В този случай копираме и трите елемента от списъка с източници в списъка с местоназначения. Методът Arrays.asList инициализира списъка с елементи, а не само с размер, следователно можем да копираме списъка с източници в списъка с дестинации успешно.

Ако просто разменим аргументите на метода Collections.copy , той ще хвърли java.lang.IndexOutOfBoundsException, тъй като размерът на списъка с източници е по-малък от размера на списъка на местоназначението .

След тази операция за копиране списъкът с дестинации изглежда така:

[11, 22, 33, 4, 5]

Заедно с метода Collections.copy , в Java има и други начини за копиране на List . Нека да разгледаме някои от тях.

4.2. Конструктор на ArrayList

Най-простият подход за копиране на Списък е използването на конструктор, който приема параметър Collection :

List source = Arrays.asList(11, 22, 33); List destination = new ArrayList(source);

Тук просто предаваме списъка с източници на конструктора на списъка с дестинации, който създава плитко копие на списъка с източници.

Списъкът на дестинациите ще бъде просто още една препратка към същия обект, посочен от списъка източник. Така че всяка промяна, направена от която и да е препратка, ще засегне един и същ обект.

Следователно използването на конструктор е добра опция за копиране на неизменяеми обекти като цели числа и низове.

4.3. добави Всички

Друг прост начин е да се използва методът addAll от Списък :

List destination = new ArrayList(); destination.addAll(source);

Методът addAll ще копира всички елементи от списъка с източници в списъка с местоназначения.

Има няколко точки, които трябва да се отбележат по отношение на този подход:

  1. Създава плитко копие на списъка с източници.
  2. Елементите на списъка с източници се добавят към списъка с дестинации.

4.4. Java 8 потоци

Java 8 представи Stream API, който е чудесен инструмент за работа с Java Collections.

Използвайки метода stream () , правим копие на списъка, използвайки Stream API :

List copy = source.stream() .collect(Collectors.toList());

4.5. Java 10

Копирането на списък е още по-просто в Java 10. Използването на метода copyOf () ни позволява да създадем неизменим списък, съдържащ елементите на дадената колекция :

List destination = List.copyOf(sourceList);

Ако искаме да използваме този подход, трябва да се уверим, че входният списък не е нулев и че не съдържа никакви нулеви елементи.

5. Заключение

В тази статия разгледахме как и защо методът Collections.copy хвърля IndexOutOfBoundException „Източникът не се записва в dest“ . Заедно с него проучихме и различни начини за копиране на списък в друг списък.

Както примерите преди Java-10, така и примерите за Java 10 могат да бъдат намерени в GitHub.