본문 바로가기

Java/Chapter 13. 배열(Array)

[Java] 13.03 - 다차원 배열의 이해와 활용

들어가며

 배열의 논리적 메모리 구조가
2차원 이상의 형태를 보이는
배열을 가리켜

 '다차원 배열'이라고 한다.

 즉 2차원배열도 다차원 배열이고,
3차원 배열도 다차원 배열이다.

 그러나 일반적인 프로그램에서는
2차원을 초과하는 구조의 배열을
잘 이용하지 않는다.

 따라서 설명의 초점을 2차원
배열에 두고자 한다.

그러나 2차원배열을 잘 알면 3차원 배열도 다룰 수 있다.

 

2차원 배열의 생성과 접근

 1차원 배열은 그 이름이 의미하듯이
둘 이상의 변수가 '선의 형태'로
존재하는 배열이다.

 반면 2차원 배열은 다수의 변수가
'면의 형태'로 존재하는 배열이다.

그림 61 - 2차원 배열의 메모리 구조

 위 그림에서 보이듯이 세로 길이와
가로 길이가 각각 3과 4인

 int형 2차원 배열은 다음과 같이
생성 한다.

int[][] arr = new int[3][4];
// 세로 길이가 3, 가로 길이가 4인 int형 2차원 배열의 생성

 즉, int[][]은 int형 2차원 배열의
참조변수형을 의미하고,

 new int[3][4]에서 3은 배열의
세로 길이를, 4는 가로 길이를
의미한다.

 이와 관련하여 몇 가지 예시를
들면 다음과 같다.

int[][] arr1 = new int[7][2];
// 세로 길이가 7, 가로 길이가 2인 int형 2차원 배열의 생성
double[][] arr2 = new double[3][5];
// 세로 길이가 3, 가로 길이가 5인 double형 2차원 배열의 생성
String[][] arr3 = new String[3][7];
// 세로 길이가 3, 가로 길이가 7인 String형 2차원 배열의 생성

 그리고 2차원 배열의 요소에
접근할 때에는

 세로와 가로의 위치를 각각
지정해야 하는데,

 1차원 배열과 마찬가지로
위치 지정의 인덱스 값은
0에서부터 시작한다

[그림 61]에서 요소별 접근 인덱스 값을 보이고 있다.
arr[1][0] = 5;
// 세로, 가로의 인덱스 위치가 각각 1, 0인 요소에 5를 저장
arr[0][1] = 7;
// 세로, 가로의 인덱스 위치가 각각 0, 1인 요소에 7을 저장

 따라서 가로세로의 길이가 모두
3인 int형 2차원 배열 arr이 다음과
같이 생성되었을 때,

그림 62 - 2차원 배열의 접근 예시

 이 배열의 좌측 상단에 위치한
다음 요소는 arr[0][0]으로 접근한다.

그림 62 - 2차원 배열의 접근 예시

 그리고 우측 하단에 위치한
다음 요소는 arr[2][2]으로 접근한다.

그림 62 - 2차원 배열의 접근 예시


 그럼 지금까지 설명한 내용을
예제를 통해서 확인해보겠다.

 이 예제에서는 세로와 가로의
길이가 각각 3과 4인 배열을
생성하고,

 좌측 상단에서부터 우측 하단까지
순서대로 정수를 저장하는데,

 그 값이 1에서부터 1씩 증가하는
형태이다.

class TwoDimenArray {
    public static void main(String[] args){
        int[][] arr = new int[3][4];
        int num = 1;

        // 배열에 값을 저장
        for (int i=0; i < 3; i++){
            for (int j=0; j < 4; j++){
                arr[i][j] = num;
                num++;
            }
        }

        // 배열에 저장된 값을 출력
        for (int i=0; i < 3; i++){
            for (int j=0; j < 4; j++)
                System.out.print(arr[i][j] + "\t");
            System.out.println();
        }
    }
}


/*
출력 결과
1	2	3	4	
5	6	7	8	
9	10	11	12	
*/

 

2차원 배열의 구조

 앞서 보인 예제 정도만 이해를
해도 2차원 배열을 활용할 수 있다.

 그러나 다음 예제에서 보이는
'자바의 2차원 배열 특성'을
이해하면

 배열을 더 잘 활용할 수 있다.

 이 예제는 이전 예제와 사실상
동일하다.

 다만 배열의 가로와 세로의 길이를
인스턴스 변수 length를 통해 확인하는
부분에서만 차이가 난다.

class TwoDimenArray2 {
    public static void main(String[] args){
        int[][] arr = new int[3][4];
        int num = 1;

        // 배열에 값을 저장
        for (int i=0; i < arr.length; i++){
            for (int j=0; j < arr[i].length; j++){
                arr[i][j] = num;
                num++;
            }
        }

        // 배열에 저장된 값을 출력
        for (int i=0; i < arr.length; i++){
            for (int j=0; j < arr[i].length; j++)
                System.out.print(arr[i][j] + "\t");
            System.out.println();
        }
    }
}

/*
출력 결과
1	2	3	4
5	6	7	8
9	10	11	12
*/

 위 예제에서 다음 2차원 배열을
생성하였다.

int[][] arr = new int[3][4];

 이때 참조변수 arr이 참조하는
배열은 다음의 형태를 띤다.

세로로 나열하였지만 이는 1차원 배열이다.

 그리고 이 배열의 길이는
arr.length를 참조하여 확인할
수 있다.

그림 63 - 2차원 배열의 구조

 위 배열의 요소는 위에서 아래로
arr[0], arr[1], arr[2]이고 이 셋 역시
참조변수이다.

 그런데 그냥 참조변수가 아닌
'1차원 배열을 참조하는 참조변수'
이다.

 그래서 이들 참조변수는 각각
길이가 4인 1차원배열을 다음과
같이 참조한다.

그림  63 - 2차원 배열의 구조

 따라서 arr[0].length, arr[1].length,
arr[2].length로 각 참조변수가 참조하는
배열의 길이를 확인할 수 있다.

 정리하면 2차원 배열은 다수의
1차원 배열이 묶여서 만들어진다.

 즉 위의 배열 생성문장을 통해서
생성되는 2차원 배열의 실제 모습은
다음과 같다.

그림 64  - 2차원 배열의 실제 구조

 물론 코드를 작성 할 때에는
2차원 배열을 [그림 61]의 구조로
생각하는 것이 옳다.

 그러나 위의 구조를 알고 있음으로써
보다 다양한 코드를 이해할 수 있다.

 예를 들면 다음과 같은 코드이다.

public static void main(String[] args){
    int[][] arr = new int[3][4];
    . . . .
    arr[1] = new int[7];    // 두 번째 줄의 배열을 교체하는 문장
    . . . .
}

 위의 코드에서는 2차원 배열의
두 번째 줄을 교체하였다.

 그것도 길이가 7인 배열로 교체하였다.

 따라서 2차원 배열이 다음의
모습으로 바뀌게 된다.

그림 65 - 다양한 형태의 다차원 배열

 이러한 내용의 코드 작성이
권장할 일은 아니지만,

 이렇게 작성된 코드의 내용을
분석하고 이해할 수는 있어야 한다.

 

2차원 배열의 초기화

 1차원 배열과 마찬가지로
2차원 배열도

 다음과 같이 생성과 동시에
초기화가 가능하다.

int[][] arr = new int[][] {
        {11, 22, 33},   // 1행 초기화
        {44, 55, 66},   // 2행 초기화
        {77, 88, 99}    // 3행 초기화
};

 위의 문장으로 인해 가로세로의
길이가 모두 3인 2차원 배열이
생성되고,

 동시에 모든 요소가 지정된
값으로 초기화된다.

 그리고 위의 문장을 대신해서
다음과 같이 쓸 수도 있다.

int[][] arr = {
        {11, 22, 33},   // 1행 초기화
        {44, 55, 66},   // 2행 초기화
        {77, 88, 99}    // 3행 초기화
};

 그렇다면 다음과 같이 초기화를
하면 어떠한 배열이 생성되는가?

 답을 확인하기 전에 나름대로
예상을 해보면 좋겠다.

int[][] arr = {
        {11},
        {22, 33},
        {44, 55, 66}
};

 위의 문장에 의해 만들어지는
배열의 구조는

 다음과 같은 간단한 예제를
통해서 확인할 수 있다.

 실행 결과를 통해서 위의 배열이
어떠한 구조를 갖는지 확인할 수
있다.

class PartiallyFilledArray {
    public static void main(String[] args){
        int[][] arr = {
                {11},
                {22, 33},
                {44, 55, 66}
        };

        // 배열의 구조대로 내용 출력
        for (int i=0; i < arr.length; i++){
            for (int j=0; j < arr[i].length; j++)
                System.out.print(arr[i][j] + "\t");
            System.out.println();
        }
    }
}

/*
출력 결과
11	
22	33	
44	55	66	
*/

 실행 결과를 통해서,

 '초기화 값의 수'에 해당하는 길이의
배열이 생성됨을 확인할 수 있다.

 즉 배열의 가로 길이가 행 별로
다른 2차원 배열이 생성된다.

 그리고 위의 예제를 제시한 이유는
이러한 배열을 만들어서 활용하라는
의미가 아니다.

물론 필요하다면 의도적으로 만들어서 활용할 수도 있다.

 초기화를 잘못하여 원치 않는
길이의 배열이 만들어지지
않도록,

 주의하라는 의미로 예제를
제시하였다.


참고 및 출처

윤성우의 열혈 Java 프로그래밍
국내도서
저자 : 윤성우
출판 : 오렌지미디어 2017.07.05
상세보기