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에서 참조하는 동일한 개체에 대한 또 다른 참조 일뿐입니다. 따라서 참조에 의한 모든 변경 사항은 동일한 객체에 영향을 미칩니다.
따라서 생성자를 사용하는 것은 Integers 및 Strings 와 같은 변경 불가능한 객체를 복사하는 데 좋은 옵션입니다 .
4.3. addAll
또 다른 간단한 방법은 List 의 addAll 메소드 를 사용하는 것입니다 .
List<Integer> destination = new ArrayList<>();
destination.addAll(source);
addAll 메소드는 소스 List의 모든 요소를 대상 List에 복사합니다.
이 접근 방식과 관련하여 몇 가지주의해야 할 사항이 있습니다.
- 소스 List의 얕은 복사본을 만듭니다.
- 소스 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의에를 통해 찾아 볼 수있다.
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/java-indexoutofboundsexception
'Java' 카테고리의 다른 글
특정 소나 위반을 제외하도록 프로젝트 구성 (0) | 2021.03.23 |
---|---|
HttpClient 요청에 매개 변수 추가 (0) | 2021.03.23 |
정수의 제곱근이 Java에서 정수인지 확인 (0) | 2021.03.22 |
RestTemplate을 사용하여 개체 List 가져 오기 및 게시 (0) | 2021.03.22 |
Spring RestTemplate을 통해 대용량 파일 다운로드 (0) | 2021.03.22 |