1. 개요

Java에서 List  의 사본을 만들면  때때로 IndexOutOfBoundsException이 발생할 수 있습니다 . "소스가 대상에 맞지 않습니다." 이 짧은 사용방법(예제)에서는 Collections.copy  메서드를 사용할 때이 오류가 발생하는 이유 와 해결 방법을 살펴 보겠습니다. 또한 List의 복사본을 만들기 위해 Collections.copy의  대안을 살펴볼 것  입니다.

2. 문제 재현

Collections.copy 메서드를 사용하여 List  의 복사본을 만드는 메서드부터 시작하겠습니다  .

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

여기서 copyList 메서드 는 원본 List의 크기와 동일한 초기 용량 으로 새 List 만듭니다 . 그런 다음 소스 List의 요소를 대상 List에 복사하려고합니다.

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

그러나 copyList 메소드를 호출하면 java.lang.IndexOutOfBoundsException : Source does not fit in dest 예외가 발생 합니다.

3. 예외의 원인

무엇이 잘못되었는지 이해하려고 노력합시다. Collections.copy 메소드에 대한 문서에 따르면 :

목적지 List은 최소한 소스 List만큼 길어야합니다. 더 길면 대상 List의 나머지 요소는 영향을받지 않습니다.

이 예에서는 소스 List의 크기와 동일한 초기 용량을 가진 생성자를 사용하여 List만들었습니다 . 단순히 충분한 메모리를 할당하고 실제로 요소를 정의하지 않습니다. 새 List의 크기는 용량과 크기가 List의 속성이 다르기 때문에 0으로 유지됩니다 .

따라서 Collections.copy  메서드가 소스 List을 대상 List에 복사하려고하면 java.lang.IndexOutOfBoundsException이 발생합니다.

4. 솔루션

4.1. Collections.copy

Collections.copy  메서드를 사용하여 List 를 다른 List 로 복사하는 작업 예제를 살펴 보겠습니다 .

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

이 경우 소스 List의 세 요소를 모두 대상 List에 복사합니다. Arrays.asList의 방법은 그러므로, 우리는 성공적으로 대상 List에 소스 List을 복사 할 수있어, 요소뿐 아니라 크기 List을 초기화한다.

Collections.copy  메소드 의 인수 만 바꾸면 소스 List의 크기가 대상 List의 크기보다 작기 때문에 java.lang.IndexOutOfBoundsException  이 발생합니다 .

이 복사 작업 후 대상 List은 다음과 같습니다.

[11, 22, 33, 4, 5]

Collections.copy 메소드 와 함께 Java에서 List 의 사본을 만드는 다른 방법이 있습니다 . 그중 일부를 살펴 보겠습니다.

4.2. ArrayList 생성자

List  를 복사하는 가장 간단한 방법 Collection 매개 변수 사용하는 생성자를 사용하는 것 입니다 .

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

여기서는 소스 List을 대상 List의 생성자에 전달하기 만하면 소스 List의 얕은 복사본이 생성됩니다.

대상 List은 소스 List에서 참조하는 동일한 개체에 대한 또 다른 참조 일뿐입니다. 따라서 참조에 의한 모든 변경 사항은 동일한 객체에 영향을 미칩니다.

따라서 생성자를 사용하는 것은 IntegersStrings같은 변경 불가능한 객체를 복사하는 데 좋은 옵션입니다 .

4.3. addAll

또 다른 간단한 방법은 ListaddAll  메소드 를 사용하는 것입니다 .

List<Integer> destination = new ArrayList<>();
destination.addAll(source);

addAll 메소드는 소스 List의 모든 요소를 ​​대상 List에 복사합니다.

이 접근 방식과 관련하여 몇 가지주의해야 할 사항이 있습니다.

  1. 소스 List의 얕은 복사본을 만듭니다.
  2. 소스 List의 요소가 대상 List에 추가됩니다.

4.4. 자바 8 스트림

Java 8은 Java 컬렉션 작업을위한 훌륭한 도구 인 Stream API 를 도입했습니다 .

은 Using 스트림 () 메소드를, 우리는 스트림 API를 사용하여 List의 복사본을 만들 :

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

4.5. 자바 10

List 복사는 Java 10에서 훨씬 더 간단합니다. copyOf () 메서드를 사용하면 주어진 Collection 의 요소를 포함하는 불변 List을 만들 수 있습니다 .

List<Integer> destination = List.copyOf(sourceList);

이 방법을 사용하려면 입력 List null 이 아니고 null 요소가 포함되어 있지 않은지 확인해야합니다 .

5. 결론

이 기사에서는 Collections.copy 메소드가 IndexOutOfBoundException“Source does not file in dest”를 던지는 방법과 이유를 살펴 보았습니다 . 이와 함께 List  를 다른  List 로 복사하는 다양한 방법을 탐색했습니다 .

모두 사전에 자바 (10)의 예자바 (10)의 예는 GitHub의에를 통해 찾아 볼 수있다.