프로그래밍/Java

[Java] Java기초 - (3) 배열

Churnobyl 2023. 11. 1. 14:14
728x90
반응형

 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것을 배열이라고 한다. 파이썬은 동적 배열인 list를 사용해서 다른 타입의 요소들을 저장할 수 있지만, 자바에서의 배열의 요소들은 모두 같은 타입이어야만 한다.


01. 배열

 


 1. 배열의 선언과 생성

 

// Case 1
int[] arr;
arr = new int[3];

// Case 2
int[] arr = new int[3];

// Case 3
int arr[] = new int[3];

// Case 4
int[] arr = {1, 2, 3};

 

 예를 들어 int배열에 대한 선언은 위의 네 가지 경우가 모두 가능하다. Case 1은 첫 줄에서 배열을 선언(배열을 다루는 참조변수 선언)하고 두번째 줄에서 배열을 생성(실제 저장공간을 생성)한다. Case 2는 선언과 동시에 배열까지 생성하는 가장 일반적인 형태다. Case 3는 C 프로그래머들이 Java에 익숙해지도록 돕기 위해 추가된 문법이지만 Java에서는 Case 2 형태를 권장한다. Case 4는 배열을 선언하고 생성하는 동시에 초기화까지 하는 문법이다.

 

 

 


2. 배열의 출력

 

import java.io.IOException;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws IOException {

        int[] arr = {1, 2, 3, 4, 5};

        System.out.println(arr);

        for (int i = 0; i < 5; i++) {
            System.out.print(arr[i] + ", ");
        }

        System.out.println();
        System.out.println(Arrays.toString(arr));

        char[] arr2 = {'j', 'a', 'v', 'a'};

        System.out.println(arr2);
        System.out.print(arr2);
    }
}
[I@4eec7777
1, 2, 3, 4, 5,
[1, 2, 3, 4, 5]
java
java

 

 배열은 인덱스를 지정해서 출력해야 각 요소를 출력할 수 있다. 위와 같이 배열 자체를 출력하면 '타입@주소'형식으로 출력된다. 그 이유는 arr 변수는 참조변수이므로 해당 변수에 저장된 값은 배열의 주소이기 때문이다.

 

 일반적으로 배열을 출력하는 방법은 위와 같이 for문을 통해 순회하며 출력하는 방법이나 Arrays.toString메서드를 이용해 대괄호([])를 포함한 String형태로 출력하는 방법이 있다.

 

 마지막으로 char배열 같은 경우에는 예외적으로 각 요소가 구분자 없이 그대로 출력된다. println이나 print메서드 둘다 마찬가지다.

 

 

 


3. 배열의 복사

 자바에서의 배열은 파이썬의 동적 배열인 list와는 달리 한번 생성하면 그 길이를 변경할 수 없다. 따라서 더 많은 저장 공간이 필요하다면 보다 큰 배열을 새로 만들고 이전 배열로부터 내용을 복사해야 한다. 자바에서 배열을 복사하는 방법은 두 가지가 있는데, 하나는 for문을 이용해 새로운 배열에 기존 배열 요소들을 복사하는 방법, 나머지 하나는 System.arraycopy메서드를 이용하는 방법이다.

 

 

for문을 이용한 복사

 

import java.io.IOException;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws IOException {

        String[] 출석부 = {"김철수", "나관중", "마동석"};
        System.out.println(Arrays.toString(출석부));

//        출석부[3] = "신경주";

        /* 출석부 새로 만들기 */
        String[] 새로_만든_출석부 = new String[출석부.length * 2];

        for (int i = 0; i < 출석부.length; i++) {
            새로_만든_출석부[i] = 출석부[i];
        }

        출석부 = 새로_만든_출석부;

        출석부[3] = "신경주";

        System.out.println(Arrays.toString(출석부));
    }
}
[김철수, 나관중, 마동석]
[김철수, 나관중, 마동석, 신경주, null, null]

 

 다음과 같이 출석부는 3명의 이름만 저장되어 있고 더 이상 새로운 학생인 '신경주'를 추가할 수 없다. 그냥 실행한다면 ArrayIndexOutOfBoundsException이 발생한다. 따라서 출석부를 새로 만들기로 하는데, 우선 새로운 출석부를 만들고 기존 출석부의 두 배 크기의 공간을 확보한다. 그리고 for문을 통해 순회하면서 기존 출석부 명부를 새로운 출석부에 복사한다. 마지막으로 기존 출석부 참조변수가 새로 만든 출석부를 가리키도록 하면 된다. 기존 출석부가 가리키던 크기가 3개짜리 배열은 이제 어느 변수에서도 참조되지 않으므로 가비지 컬렉터에 의해 메모리에서 자동으로 제거된다.

 

 

 

System.arraycopy를 이용한 복사

 

import java.io.IOException;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws IOException {

        String[] 출석부 = {"김철수", "나관중", "마동석"};
        System.out.println(Arrays.toString(출석부));

        String[] 새로운_출석부 = new String[출석부.length * 2];

        System.arraycopy(출석부, 0, 새로운_출석부, 0, 출석부.length);

        System.out.println(Arrays.toString(새로운_출석부));


        int[] number1 = {1, 2, 3, 4, 5};
        int[] number2 = {6, 7, 8, 9};

        int[] result = new int[number1.length + number2.length];
        System.arraycopy(number1, 0, result, 0, number1.length);
        System.arraycopy(number2, 0, result, number1.length, number2.length);

        System.out.println(Arrays.toString(result));
    }
}
[김철수, 나관중, 마동석]
[김철수, 나관중, 마동석, null, null, null]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

 

 A배열을 B배열로 0번째 인덱스부터 전부 복사한다고 하면 System.arraycopy(A, 0, B, 0, A.length)라고 쓸 수 있다. 즉, arraycopy에 들어가는 파라미터는 A배열의 몇 번째 요소부터 B배열의 몇 번째 요소로 몇 개의 값을 복사할 것인지를 지정해주는 것이다.

 

 arraycopy는 native 키워드가 붙은 걸로 보아 자바가 아닌 C나 C++로 구현되었으므로 기존 for를 이용한 방법보다 더 빠를 것으로 유추할 수 있다.

반응형