Java에서 배열을 복사하는 방법

1. 개요

이 빠른 기사에서는 Java의 다양한 배열 복사 방법에 대해 설명합니다. 배열 복사는 사소한 작업처럼 보일 수 있지만 신중하게 수행하지 않으면 예기치 않은 결과 및 프로그램 동작이 발생할 수 있습니다.

2. 시스템 클래스

핵심 Java 라이브러리 인 System.arrayCopy () 부터 시작하겠습니다 . 그러면 지정된 길이까지 소스 위치에서 대상 위치로 복사 작업을 시작하여 소스 배열에서 대상 배열로 배열을 복사합니다.

대상 배열에 복사 된 요소의 수가 지정된 길이와 같습니다. 배열의 하위 시퀀스를 다른 배열로 쉽게 복사 할 수있는 방법을 제공합니다.

어레이의 모든 인수이면 널은 그것이 발생 NullPointerException이 상기 정수 인자 중 음극이나 범위를 벗어나는 경우가 발생 IndexOutOfBoundException를 .

java.util.System 클래스를 사용하여 전체 배열을 다른 배열에 복사하는 예제를 살펴 보겠습니다 .

int[] array = {23, 43, 55}; int[] copiedArray = new int[3]; System.arraycopy(array, 0, copiedArray, 0, 3);

이 메서드가 취하는 인수는 다음과 같습니다. 소스 배열, 소스 배열에서 복사 할 시작 위치, 대상 배열, 대상 배열의 시작 위치 및 복사 할 요소 수.

소스 배열에서 대상으로 하위 시퀀스를 복사하는 방법을 보여주는 또 다른 예를 살펴 보겠습니다.

int[] array = {23, 43, 55, 12, 65, 88, 92}; int[] copiedArray = new int[3]; System.arraycopy(array, 2, copiedArray, 0, 3); 
assertTrue(3 == copiedArray.length); assertTrue(copiedArray[0] == array[2]); assertTrue(copiedArray[1] == array[3]); assertTrue(copiedArray[2] == array[4]); 

3. 어레이 클래스

배열 클래스는 다른 배열을 복사하는 여러 오버로드 된 방법을 제공합니다. 내부적으로는 앞에서 보았던 System 클래스에서 제공하는 것과 동일한 접근 방식을 사용합니다 . 주로 copyOf (…)copyRangeOf (…) 두 가지 메서드를 제공합니다 .

먼저 copyOf를 살펴 보겠습니다 .

int[] array = {23, 43, 55, 12}; int newLength = array.length; int[] copiedArray = Arrays.copyOf(array, newLength); 

Arrays 클래스는 소스 배열 길이의 최소값을 선택하는 데 Math.min (…) 을 사용 하고 결과 배열의 크기를 결정하는 새 길이 매개 변수의 값을 사용 한다는 점에 유의해야합니다 .

Arrays.copyOfRange ()는 '2 개 파라미터를 취 에서' 과 ' 을' 소스 배열 변수 이외에. 결과 배열에는 ' from' 인덱스가 포함되지만 'to' 인덱스는 제외됩니다. 예를 보겠습니다.

int[] array = {23, 43, 55, 12, 65, 88, 92}; int[] copiedArray = Arrays.copyOfRange(array, 1, 4); 
assertTrue(3 == copiedArray.length); assertTrue(copiedArray[0] == array[1]); assertTrue(copiedArray[1] == array[2]); assertTrue(copiedArray[2] == array[3]);

이 두 방법 모두 원시가 아닌 객체 유형의 배열에 적용될 경우 객체의 단순 복사수행합니다 . 예제 테스트 케이스를 보겠습니다.

Employee[] copiedArray = Arrays.copyOf(employees, employees.length); employees[0].setName(employees[0].getName() + "_Changed"); assertArrayEquals(copiedArray, array);

결과는 얕은 복사본이기 때문에 원본 배열 요소의 직원 이름이 변경되어 복사본 배열이 변경되었습니다.

그래서 – 만약 우리가 원시 타입이 아닌 타입의 딥 카피를 원한다면 – 우리는 다음 섹션에서 설명하는 다른 옵션으로 갈 수 있습니다.

4. Object.clone ()을 사용한 어레이 복사

Object.clone () 은 배열의 Object 클래스에서 상속 됩니다.

먼저 clone 메서드를 사용하여 기본 유형의 배열을 복사 해 보겠습니다.

int[] array = {23, 43, 55, 12}; int[] copiedArray = array.clone(); 

그리고 그것이 작동한다는 증거 :

assertArrayEquals(copiedArray, array); array[0] = 9; assertTrue(copiedArray[0] != array[0]);

위의 예는 복제 후 동일한 콘텐츠를 가지고 있지만 참조가 서로 다르므로 변경 사항이 다른 항목에 영향을주지 않습니다.

반면에 동일한 방법을 사용하여 원시 유형이 아닌 유형의 배열을 복제하면 결과가 달라집니다.

포함 된 객체의 클래스가 Cloneable 인터페이스를 구현 하고 Object 클래스 의 clone () 메서드를 재정의 하더라도 기본 형식이 아닌 배열 요소 의 얕은 복사본 을 만듭니다 .

예를 살펴 보겠습니다.

public class Address implements Cloneable { // ... @Override protected Object clone() throws CloneNotSupportedException { super.clone(); Address address = new Address(); address.setCity(this.city); return address; } } 

새로운 주소 배열을 만들고 clone () 메서드를 호출하여 구현을 테스트 할 수 있습니다 .

Address[] addresses = createAddressArray(); Address[] copiedArray = addresses.clone(); addresses[0].setCity(addresses[0].getCity() + "_Changed"); 
assertArrayEquals(copiedArray, addresses);

이 예제는 원본 또는 복사 된 배열의 변경으로 인해 포함 된 객체가 Cloneable 인 경우에도 다른 배열이 변경됨을 보여줍니다 .

5. Stream API 사용

배열 복사에도 Stream API를 사용할 수 있습니다. 예를 살펴 보겠습니다.

String[] strArray = {"orange", "red", "green'"}; String[] copiedArray = Arrays.stream(strArray).toArray(String[]::new); 

원시 유형이 아닌 경우에는 객체의 얕은 복사도 수행합니다. Java 8 Streams 에 대해 자세히 알아 보려면 여기에서 시작할 수 있습니다.

6. 외부 라이브러리

Apache Commons 3 offers a utility class called SerializationUtils that provides a clone(…) method. It is very useful if we need to do a deep copy of an array of non-primitive types. It can be downloaded from here and its Maven dependency is:

 org.apache.commons commons-lang3 3.5  

Let's have a look at a test case:

public class Employee implements Serializable { // fields // standard getters and setters } Employee[] employees = createEmployeesArray(); Employee[] copiedArray = SerializationUtils.clone(employees); 
employees[0].setName(employees[0].getName() + "_Changed"); assertFalse( copiedArray[0].getName().equals(employees[0].getName()));

This class requires that each object should implement the Serializable interface. In terms of performance, it is slower than the clone methods written manually for each of the objects in our object graph to copy.

7. Conclusion

In this tutorial, we had a look at the various options to copy an array in Java.

사용 방법은 주로 정확한 시나리오에 따라 다릅니다. 기본 유형 배열을 사용하는 한 SystemArrays 클래스 에서 제공하는 모든 메서드를 사용할 수 있습니다 . 성능에 차이가 없어야합니다.

원시 유형이 아닌 경우 배열의 전체 복사를 수행해야하는 경우 SerializationUtils 를 사용 하거나 클래스에 클론 메서드를 명시 적으로 추가 할 수 있습니다 .

항상 그렇듯이이 기사에 표시된 예제는 GitHub에서 사용할 수 있습니다.