[Java] 다시 정리하는 "배열"

rara_kim·2022년 11월 12일
0

Java

목록 보기
29/39
post-thumbnail

배열

배열은 같은 타입의 데이터를 연속된 공간에 나열하고, 각 데이터에 인덱스를 부여해놓은 자료구조이다.

int score1 = 83;
int score2 = 90;
int score3 = 87;
	.
	.
	.
int score30 = 75;

위의 데이터는 다음과 같이 배열로 생성할 수 있다.

score 배열의 각 인덱스는 각 항목의 데이터를 읽거나 저장하는 데 사용되며 아래와 같이 배열 이름 옆에 대괄호 []에 기입된다.  그리고 인덱스는 0부터 시작한다.

score[인덱스]

배열의 특징

1️⃣배열은 같은 타입의 데이터만 저장할 수 있다.

int 배열은 int 값만 저장 가능하고, String 배열은 문자열만 저장 가능하다.
또한 선언과 동시에 저장할 수 있는 타입이 결정된다.
만약, 다른 타입의 값을 저장하려고 하면 타입 불일치(Type mismatch) 컴파일 에러가 발생한다.

2️⃣한번 생성된 배열은 길이를 늘리거나 줄일 수 없다.

3개의 값을 저장하는 배열을 생성했다고 가정해보자.
프로그램 실행 도중에 5개의 값을 저장하는 배열로 수정할 수 없고, 반대로 2개의 값만 저장하는 배열로 수정할 수도 없다.
만약, 5개의 값을 저장해야하는 경우가 발생한다면 길이 5의 새로운 배열을 생성하고, 기존 배열 항목을 새 배열로 복사해야 한다.

배열의 선언

배열을 사용하기 위해서는 배열 변수를 먼저 선언해야 하는데, 배열 변수 선언은 두 가지 형식으로 작성할 수 있다.

형식1:    타입[ ] 변수;
형식2:    타입 변수[ ];

대괄호[]는 배열 변수를 선언하는 기호로 사용되는데, 타입 뒤 혹은 변수 뒤에 붙을 수 있다.

int[] intArray;
double[] doubleArray;
String[] strArray;

int intArray[];
double doubleArray[];
String strArray[];

배열 변수는 참조 변수에 속한다. 배열도 객체이므로 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 객체를 참조하게 된다.
참조할 배열 객체가 없다면 배열 변수는 null 값으로 초기화될 수 있다.
만약 배열 변수가 null 값을 가진 상태에서 변수[인덱스]로 값을 읽거나 저장하게 되면 NullPointerException이 발생한다.
배열을 생성하고 배열 변수가 참조하는 상태에서 값을 저장하거나 읽어야 한다.

타입[ ] 변수 =  null;

배열 생성

배열 객체를 생성하려면 값 목록을 이용하거나 new 연산자를 이용하는 방법이 있다.

1️⃣값 목록으로 배열 생성

타입[] 변수 = {0,1,2,3, ... };

중괄호 {}는 주어진 값들을 항목으로 가지는 배열 객체를 힙에 생성하고, 배열 객체의 번지를 리턴한다.
배열 변수는 리턴된 번지를 저장함으로써 참조할 수 있다.

💡값의 목록으로 배열 객체를 생성할 때 주의할 점
 배열 변수를 이미 선언한 후에는 다른 실행문에서 중괄호를 사용한 배열 생성이 허용되지 않는다.
new 연산자를 사용해서 값 목록을 지정해 주어야 한다.

타입[] 변수;
변수 = {0,1,2,3, ... };             //NG, 컴파일 에러
변수 = new 타입[] {0,1,2,3, ... };   //OK

2️⃣new 연산자로 배열 생성

값의 목록을 가지고 있지 않지만, 향후 값들을 저장할 배열을 미리 만들고 싶다면 new 연산자로 배열 객체를 생성할 수 있다.

타입[ ] 변수 = new 타입[길이];

길이는 배열이 저장할 수 있는 값의 개수를 말한다.
이미 배열 변수가 선언된 경우에도 new 연산자로 배열을 생성할 수 있다.

타입[ ] 변수 = null;
변수 = new 타입[길이];

new 연산자로 배열을 처음 생성할 경우 배열은 자동적으로 기본값으로 초기화된다.

분류타입초기값
기본 타입(정수)byte[ ]
char[ ]
short[ ]
int[ ]
long[ ]
0
'\u0000'
0
0
0L
기본 타입(실수)float[ ]
double[ ]
0.0F
0.0
기본 타입(논리)boolean[ ]false
참조 타입클래스[ ]
인터페이스[ ]
null
null

배열이 생성되고 나서 특정 인덱스 위치에 새로운 값을 저장하려면 대입 연산자를 사용하면 된다.

int[] scores = new int[3];
scores[0] = 83;
scores[1] = 90;
scores[2] = 75;

배열 길이

배열의 길이란 배열에 저장할 수 있는 전체 항목의 개수를 말한다.
코드에서 배열의 길이를 얻으려면 배열 객체의 length필드(객체 내부의 데이터)를 읽으면 되는데, length 필드는 읽기 전용 필드이기 때문에 값을 바꿀 수 없다.

int[] intArray = {10, 20, 30};
int num = intArray.length;

intArray.length = 10;      //NG

배열의 인덱스 범위는 0 ~ (길이 - 1)인데, 만약 인덱스를 초과해서 사용하면 ArrayIndexOutOfBoundsException이 발생한다.

다차원 배열

다차원 배열이란 2차원 이상의 배열을 의미하며, 배열 요소로 또 다른 배열을 가지는 배열을 의미한다.
위에서 살펴본 배열과 달리 값들이 행과 열로 구성된 배열을 2차원 배열이라고 하며, 2차원 배열은 가로 인덱스와 세로 인덱스를 사용한다.

자바는 2차원 배열을 중첩 배열 방식으로 구현한다. 예를 들어 2(행) x 3(열) 행렬을 만들기 위해서는 아래와 같은 코드를 사용한다.

int[][] myArray = new int[2][3];

예를 들어, 그룹화된 성적 점수를 이용해서 아래와 같은 2차원 배열을 만들 수 있다.
scores[0]에는 {95, 80} 배열을 참조하고, scores[1]에는 {92, 96} 배열을 참조한다.

int[][] scores = {{95, 80}, {92, 96}};

위 코드로 생성된 scores 배열에서 각 항몫 값은 아래와 같이 읽을 수 있다.

int score1 = scores[0][0];              //95
int score2 = scores[1][1];              //96

객체를 참조하는 배열

기본 타입 배열은 각 항목에 직접 값을 갖고 있지만,  참조 타입(클래스, 인터페이스) 배열은 각 항목에 객체의 번지를 가지고 있다.
예를 들어 String은 클래스이므로 String[] 배열은 각 항목에 문자열이 아니라, String 객체의 번지를 가지고 있다. String[] 배열은 String 객체를 참조하게 된다.

String[][] strArray = new String[3];
strArray[0] = "Java";
strArray[1] = "Kotlin";
strArray[2] = "Python";

따라서 String[] 배열의 항목도 결국 String 변수와 동일하게 취급되어야 한다.
예를 들어 String[] 배열 항목 간에 문자열을 비교하기 위해서는 ==연산자 대신 equals()메소드를 사용해야 한다.

String[] strArray = new String[3];
strArray[0] = "Java";
strArray[1] = "Java";
strArray[2] = new String("Java");

System.out.println(strArray[0] == strArray[1]);       //true
System.out.println(strArray[0] == strArray[2]);       //false
System.out.println(strArray[0].equals(strArray[2]);   //true

배열 복사

배열은 한 번 생성하면 크기를 변경할 수 없기 때문에 더 많은 저장 공간이 필요하다면 더 큰 배열을 새로 만들고 이전 배열로부터 항목 값들을 복사해야한다.
배열 간의 항목 값들을 복사하려면 for문을 사용하거나 System.arraycopy() 메소드를 사용한다.

for문을 사용하는 경우

int[] oldIntArray = {1, 2, 3};
int[] newIntArray = new int[5];

for(int i = 0; i < oldIntArray.length; i++) {
	newIntArray[i] = oldArray[i];
}

for(int i = 0; i < newIntArray.length; i++) {
	System.out.print(newIntArray + " ");       //1 2 3 0 0
}

System.arraycopy()를 사용하는 경우

String[] oldStrArray = {"java", "array", "copy"};
String[] newStrArray = new String[5];

System.arraycopy(oldStrArray, 0, newStrArray, 0, oldStrArray.length);

for (int i = 0; i < newStrArray.length; i++) {
	System.out.print(newStrArray[i] + " ");      //java array copy null null
}

다차원 배열의 복사: System.arraycopy()를 사용

int[][] myArray1 = {{1, 3},{5, 7}};
int[][] myArray2 = {{2, 4, 6}, {8, 10, 12}};
for (int i = 0; i < myArray1.length; i++) {
	System.arraycopy(myArray1[i], 0, myArray2[i], 0, myArray1[i].length);
}

for(int i = 0; i < myArray2.length; i++) {
	for(int j = 0; j < myArray2[i].length; j++) {
		System.out.println("myArray2[" + i + "][" + j + "] = " + myArray2[i][j]);
	}
}


//출력 결과
myArray2[0][0] = 1
myArray2[0][1] = 3
myArray2[0][2] = 6
myArray2[1][0] = 5
myArray2[1][1] = 7
myArray2[1][2] = 12
profile
느리더라도 꾸준하게

0개의 댓글