다차원 배열 162p
위에 작성했던 배열은 값 목록으로 구성된 1차원 배열입니다.
이와는 달리 값들이 행과 열로서 구성된 배열을 2차원 배열이라고 하는데. 2차원 배열은 수학의 행렬을 떠올리면 되는데, 가로 인덱스와 세로 인덱스를 사용합니다.
자바 2차원 배열을 중첩 배열 방식으로 구현하는데 예를 들어 2x3 행렬을 만들기 위해서는
int[][] scores = new int[2][3];
이렇게 코드를 작성하면 됩니다. 위에 코드는 메모리에 세 개의 배열 객체를 생성합니다.
배열 변수인 scores는 길이 2인 배열 A를 참조합니다. 배열 A의 scores[0]은 다시 길이 3인 배열 B를 참조하는데
scores[1] 역시 길이 3인 배열 C를 참조합니다. scores[0]과 scores[1]은 모두 배열을 참조하는 변수 역할을 합니다.
따라서 각 배열의 길이는 다음과 같이 얻을 수 있습니다.
scores.length // 2(배열 A의 길이)
scores[0].length // 3(배열 B의 길이)
scores[1].length // 3(배열 c의 길이)
생성 원리는 수학 행력과는 근본적으로 다르지만 사용 방식은 행렬과 동일합니다.
자바는 일차원 배열이 서로 연결된 구조로 다차원 배열을 구현하기 때문에 수학 행렬 구조가 아닌 계단식 구조를 가질 수 있습니다.
int[][] scores = new int[2][];
scores[0] = new int[2]; / 0 1
scores[1] = new int[3]; / 0 1 2
위 코드는 메모리에 다음과 같이 배열 객체를 생성시킵니다.
이 경우 배열 항목의 수를 조사해보면 밑에와 같습니다.
scores.length // 2(배열 A의 길이)
scores[0].length // 2(배열 B의 길이)
scores[1].length // 3(배열 C의 길이)
이런 형태의 배열에 주의할 점은 정확한 배열의 길이를 알고 인덱스를 사용해야 합니다.
scores[0][2]는 ArrayIndexOutOfBoundsException을 발생시킵니다.
이유는 B객체의 마지막 인덱스는 1이기 때문입니다. 하지만 scores[1][2]는 배열 c 객체의 세 번째 항목을 가르킵니다.
만약 그룹화 된 값 목록을 가지고 있다면 다음과 같이 중괄호 안에 다시 중괄호를 이용해서 값 목록을 나열 해주면 됩니다.
타입[ ][ ] 변수 = {{값1, 값2,....},{값1, 값2,....},....};
그룹 0값 목록 그룹 1값 목록
예를 들면 그룹화된 성적 점수를 이용해서 다음과 같은 배열을 만들수 있습니다.
scores[0]에는 {95, 80} 배열을 참조하고, scores[1]에는 {92, 96} 배열을 참조합니다.
int[ ][ ] = scores {{95, 80},{92, 96}};
위 코드로 생성된 scores 배열에서 항목 값은 다음과 같이 읽을 수 있습니다.
int score = scores[0][0]; // 95
int score = scores[1][1]; // 96
배열속의 배열 예제
package com.javateam.score.domain;
public class ArrayInArrayEx {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] mathScores = new int[2][3];
for (int i = 0; i < mathScores.length; i++) {
for (int k = 0; k < mathScores[i].length; k++) {
System.out.println("mathScores[" + i + "][" + k + "]=" + mathScores[i][k]);
}
}
System.out.println();
int[][] englishScores = new int[2][];
englishScores[0] = new int[2];
englishScores[1] = new int[3];
for (int i = 0; i < englishScores.length; i++) {
for (int k = 0; k < englishScores[i].length; k++) {
System.out.println("englishScores[" + i + "][" + k + "]=" + englishScores[i][k]);
}
}
System.out.println();
int[][] javaScores = { { 95, 80 }, { 92, 96, 80 } };
for (int i = 0; i < javaScores.length; i++) {
for (int k = 0; k < javaScores[i].length; k++) {
System.out.println("javaScores[" + i + "][" + k + "]=" + javaScores[i][k]);
}
}
}
}
결과 출력
객체를 참조하는 배열
기본 타입(bytem char, short, int, long, float, double, boolean) 배열은 각 항목에 직접 값을 갖고 있지만, 참조 타입 (클래스, 인터페이스) 배열은 각 항목에 객체의 번지를 가지고 있습니다.
예를 들어 String 은 클래스 타입이므로 String[] 배열은 각 항목에 문자열이 아닌 String 객체의 주소를 가지고 있습니다.
즉 String 객체를 참조하게 됩니다.
String[] strArray new String[3];
strArray[0] = "Java";
strArray[1] = "C++";
strArray[2] = "C#";
위 코드는 배열 변수 strArray를 선언하고 3개의 문자열을 참조하는 배열을 생성합니다.
따라서 String[] 배열의 항목도 결국 String 변수와 동일하게 취급 되어야 합니다.
String[] 배열 항목간에 문자열을 비교하기 위해서는 == 연산자 대신 equals() 메소드를 사용해야 합니다.
== 객체의 번지 비교이기 때문에 문자열을 비교 할 수 없습니다.
Stirng[] strArray = new String[3];
strArray[0] = "java';
staArray[1] = "java";
strArray{2} = new String("java");
System.out.println( strArray[0] == strArray[1]); // true 같은 객체를 참조합니다.
System.out.println( strArray[0] == strArray[2]); // flase 같은 객체를 참조합니다.
System.out.println( strArray[0].equals(strArray[1])); // true 문자열이 동일합니다..
위 코드를 실행하면 메모리에 다음과 같이 배열 객체가 생성됩니다.
strArray[0]과 strArray[1] 배열 항목을 == 연산하면 결과는 true가 나옵니다. 이유는 동일한 String 객체를 참조하기 때문입니다.
반면에 String 객체를 new 연산자로 생성하면, 무조건 새로운 String 객체가 생성되기 때문에 strArray[0]과 strArray[2] 배열 항목을 == 연산하면 결과는 false가 나옵니다.
strArray[0]과 strArray[2] 는 서로 다른 객체를 참조하고 있기 때문입니다. 하지만 문자열은 같아서 equals() 메소드 사용시 값이 true가 나오는 것입니다.
배열 복사
배열은 한 번 생성하면 크기를 변경할 수 없기 때문에 더 많은 저장 공간이 필요하다면 보다 큰 배열을 새로 만들고 이전 밸열로부터 항목 값들을 복사해야 합니다.
배열 간의 항목 값들을 복사하려면 for문을 사용하거나 System.arraycopy() 메소드를 사용하면 됩니다. for문으로 배열을 복사하는 코드는 다음과 같습니다.
for문으로 복사 해보았을때
package com.javateam.score.domain;
public class ArrayCopyByForEx {
public static void main(String[] args) {
int[] oldIntArray = {1, 2, 3};
int[] newIntArray = new int[5];
for(int i=0; i<oldIntArray.length; i++) {
newIntArray[i] = oldIntArray[i];
}
for(int i=0; i<newIntArray.length; i++) {
System.out.print(newIntArray[i] + ",");
}
}
}
값을 출력해보면 1,2,3,,0,0 이나옵니다. 이 코드와 같이 복사되지 않는 항목은
int[] 배열의 기본 초기값인 0이 그래도 유지됩니다.
이번에는 Systrem.arraycopy() 메소드를 이용해서 배열을 복사해보겠습니다.
Systrem.arraycopy()를 호출하는 방법입니다.
System.arraycopy(Object src, int srcPos, Object dest, int destPosm int length);
src 매개값은 원본 배열이고, srcPos는 원본 배열에서 복사할 항목의 시작 인덱스 입니다. dest 매개 값은 새 배열이고, destPos는 새 배열에서 붙여넣을 시작 인덱스 입니다. 마지막으로 length는 복사할 개수를 뜻합니다.
예를 들어 arr1이 원본배열이고 새 배열이 arr2일 경우 arr1의 모든 항목을 arr2에 복사한다고 Systrem.arraycopy()를 사용하면 이렇게 코드를 작성하면 됩니다.
System.arraycopy(arr1, 0, arr2, 0, arr1.length);