프로그래밍 언어/JAVA(자바)

[자바/java] 효율적인 배열 복사 System.arrayCopy

냠냠:) 2020. 9. 24. 13:45
반응형

대량의 배열 데이터를 처리해야 하는 문제를 풀다 알게 된 방법이다. 두고두고 사용할 일이 있을 것 같아서 정리하게 되었다.

 

흔히 배열에서 리스트로, 2차원 배열에서 1차원 배열로 구조를 변경할 때 반복문을 사용해서 복사하게 된다. 

 

이는 데이터를 삽입하기 위한 불필요한 작업이 반복적으로 발생하여 매우 비효율적인 방법이다. 

 

예를 들어, 

1
2
3
4
5
6
7
8
9
10
        int[] a = new int[5];
        int[] b = new int[5];
 
        for(int i = 0; i < a.length; i++) {
            a[i] = i;
        }
        
        for(int i = 0; i < b.length; i++) {
            b[i] = a[i];
        }
cs

배열 -> 배열이거나, 

 

1
2
3
    for(int i = 0; i < al.size(); i++) {
            b[i] = al.get(i);
    }
cs

리스트 -> 배열(또는 반대)일 때다.

 

이 방법 외에도 clone을 이용해 복사하는 방법이 있는데 그 방식 또한 비효율적이다. 

 

소스코드는 매우 간결하지만 원본 배열의 값을 모두 복제해 또 하나의 배열을 생성하는 과정에서 자원이 낭비되고 실행 속도 또한 반복문을 이용한 복사보다 빠르지만 크게 차이가 나지 않는다. 추가로 원본 배열과 복사본 배열의 자료형이 같아야 한다는 제약도 있다.

 

해결 방안

"System" 클래스에는 배열을 복사하는 "arraycopy" 메소드가 존재한다. 

 

자바의 배열의 값을 복사할 경우 사용하는데 사용 방법은 다음과 같다.

System.arraycopy(src, srcPos, dest, destPos, length);

src - 원본 배열
srcPos - 원본 배열의 복사 시작 위치
dest - 복사할 배열
destPost - 복사할 배열의 복사 시작 위치
length - 복사할 요소의 개수
728x90

 

1. 기본 방식

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    public static void main(String[] args) {
        int[] a = new int[5];
        int[] b = new int[5];
 
        for(int i = 0; i < a.length; i++) {
            a[i] = i;
        }
        
        System.arraycopy(a, 0, b, 0, a.length);
        
        for(int e : b) {
            System.out.print(e+" ");
        }
    }
    // 출력 : 0 1 2 3 4 
    
cs

위와 같은 방식으로 사용한다. 이 방식의 장점은, 원하는 부분만 복사할 수 있다는 점과 불필요한 인스턴스 생성을 방지하여 메모리 자원 낭비를 예방하고, 더 빠르게 실행된다는 점이다. 가독성 측면에서도 효율적이다. 

 

 

2. 2차원 배열 -> 1차원 배열

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {
        int[][] a = new int[5][5];
        int[] b = new int[a.length * a.length];
 
        for(int i = 0; i < a.length; i++) {                //데이터를 넣는 부분
            for(int j = 0; j < a.length; j++) {
                a[i][j] = i;
            }
        }
        
        for(int i = 0; i < a.length; i++) {                //배열 복사
            System.arraycopy(a[i], 0, b, i * a.length, a.length);
        }
        
        for(int e : b) {
            System.out.print(e+" ");
        }
}
//출력 : 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 
cs

 

 

3. 리스트 -> 배열

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    public static void main(String[] args) {
        List<Integer> al = new ArrayList<Integer>();
        Integer[] b = new Integer[5];
 
        for (int i = 0; i < b.length; i++) {     // 데이터를 넣는 부분
            b[i] = i;
        }
        
        al = (List<Integer>) Arrays.asList(b);    // 배열 -> 리스트 복사
        
        for (int e : al) {
            System.out.print(e + " ");
        }
    }
    // 0 1 2 3 4
cs

 

*작은 데이터면서 자료형이 같을 때는 clone 방식의 복사가 개인적으론 더 편하다고 생각한다. 하지만 데이터가 대량이면서 부분부분 복사할 일이 있을 때는 System.arraycopy를 사용하는 것을 추천한다.

 

 

 

 

 

References

리스트와 배열 간 빠른 복사 방법 : wikibook.co.kr/article/java-coding-with-pmd-usearraysaslist/

System.arraycopy 배열 복사하기 : improver.tistory.com/124

반응형