[java] 5.배열


배열이란



이번 시간에는 배열에 대해서 알아보겠습니다.

배열이란 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것을 말합니다.

많은 양의 데이터를 저장하기 위해서, 그 데이터의 숫자만큼 변수를 선언해야 한다면

매우 혼란스러울 것입니다.

예를 들어 int형 변수 5개를 선언해야한다면 다음과 같이 해야합니다.


int num1, num2, num3, num4, num5; 



변수의 길이가 많아지면 선언도 많이 해야해서 불편한 점도 있지만,

저 많은 변수들을 다루기에도 너무 불편합니다.

예를 들어 다섯개의 변수를 출력할 때도 다음과 같이 println을 일일이 호출해야합니다.


System.out.println(num1);

System.out.println(num2);

System.out.println(num3);

System.out.println(num4);

System.out.println(num5);



하지만 이 때 배열을 사용하면 간단히 처리할 수 있습니다.



배열의 선언과 생성



배열의 선언은 다음과 같이 합니다.


타입[] 변수이름; //배열을 선언(배열을 다루기 위한 참조변수 선언)

변수이름=new 타입[길이]; //배열을 생성(실제 저장공간을 선언)



그럼 배열을 사용하여 int형 정수를 5개 선언해보겠습니다.


>int num[]=new int[5]; //int형 정수 5개를 저장할 수 있는 배열을 생성



배열의 요소는 다음과 같이 인덱스를 이용해서 접근합니다.


num[1]=5; //배열 2번째 요소에 5를 대입

num[3]=3; //배열 4번째 요소에 3을 대입



아까 일일이 println문을 호출했던 것도 반복문을 사용해서 간단하게 처리할 수 있습니다.


for(int i=0;i<5;i++){
	num[i];
}



for문을 자세히 보면 num[0], num[1], num[2], num[3], num[4]를 출력하고 있습니다.


이 때 알 수 있듯이 배열의 시작번지는 1번지가 아닌 0번지라는 것입니다.



배열의 길이와 인덱스



생성된 배열의 각 저장공간을 배열의 요소라고 하며,

아까 봤듯이 배열이름[인덱스]의 형식으로 배열의 요소에 접근합니다.

인덱스는 배열의 요소마다 붙여진 일련번호로 각 요소를 구별하는데 사용됩니다.

위에서 봤듯이


인덱스의 범위는 0부터 배열길이-1 까지 입니다.



따라서 다음과 같은 코드는 컴파일 오류를 발생시킵니다.


int[] num=new int[5];

num[5]=3; //컴파일 오류 배열의 인덱스 범위는 0~4까지 입니다.



배열의 길이



앞서 봤던 것과 같이 배열을 생성할 때 괄호 []안에 배열의 길이를 적어줘야 하는데,

배열의 길이는 배열의 요소의 개수, 즉 값을 저장할 수 있는 공간에 갯수입니다.

당연하게도 배열의 길이는 양의 정수이어야 하며 최대값은 int타입의 최대값, 약 20억입니다.


//타입[] 배열이름=new 타입[길이];

int[] arr=new int[5]; //길이가 5인 int 배열



또 신기하게도 길이가 0인 배열도 선언가능합니다.


int[] arr=new int[0]; //가능



배열의 길이는 다음과 같이 알 수 있습니다.


배열이름.length




int length=arr.length //배열 arr의 길이를 반환해준다.



배열은 한 번 생성하면 길이를 변경할 수 없기 때문에, 이미 생성된 배열의 길이는 변하지 않습니다.

따라서 배열이름.length는 상수입니다. 즉, 값을 읽을 수만 있을 뿐 변경할 수는 없습니다.


int[] score=new int[6];

arr.length=10; //에러 발생



그러면 이미 생성한 배열의 길이를 변경하고자 했을 때는 어떻게 해야할까요?


<배열의 길이를 변경하는 방법>

1. 더 큰 배열을 새로 생성한다.

2. 기존 배열의 내용을 새로운 배열에 복사한다. // 좀 있다 배웁니다.



위의 작업들은 꽤나 비용이 많이 들기 때문에, 처음부터 배열의 길이를 넉넉하게 잡아주는 것이 좋습니다.



배열의 초기화



배열은 생성과 동시에 자동적으로 자신의 타입에 해당하는 기본값으로 초기화되므로

배열을 사용하기 전에 따로 초기화를 해주지 않아도 되지만,

원하는 값을 저장하려면 아래와 같이 각 요소마다 값을 지정해 줘야합니다.


int[] score=new int[5];
score[0]=50;
score[1]=60;
score[2]=70;
score[3]=80;
score[4]=90;



초기화되는 값이 일정한 규칙이 있다면 for문을 사용하는 것이 좋습니다.


for(int i=0;i<score.length;i++){
	score[i]=i*10+50;
}



일정한 규칙이 없다면 다음과 같이 배열을 간단히 초기화 할 수 있습니다.


int[] score=new int[]{50,60,70,80,90}; //배열의 생성과 초기화를 동시에



다음과 같이 new int[]를 생략할 수도 있습니다.


int[] score={50,60,70,80,90}; //new int 생략

하지만 주의해야할 것이 선언과 생성을 따로 하는 경우에는 new int[]를 생략할 수 없습니다.


int[] score;

score=new int[]{50,60,70,80,90}; //OK

score={50,60,70,80,90}; //에러



또, 메서드의 매개변수로 사용할 때도 생략 불가합니다.


int add(int[] arr){/* 내용 생량 */}

int result(new int[]{50,60,70,80,90}); //OK

int result({50,60,70,80,90}); //에러



배열의 복사



배열은 한 번 생성하면 그 길이를 변경할 수 없기 때문에 더 많은 저장공간이 필요하다면 보다

큰 배열을 새로 만들고 이전 배열로부터 내용을 복사해야한다고 했습니다.

배열을 복사하는 방법에는 두 가지가 있는데 먼저 for문을 이용해서 복사하는 방법을 알아보겠습니다.


int[] arr=new int[5];

int[] tmp=new int[arr.length*2]; //기존배열보다 길이가 2배인 배열 생성

for(int i=0;i<arr.length;i++)
	tmp[i]=arr[i]; //arr[i]의 값을 tmp[i]에 저장
	
arr=tmp; //참조변수 arr이 새로운 배열 tmp를 가리키게 된다



arr=tmp 하면 arr와 tmp가 이름만 다를 뿐 같은 배열을 가리키게 됩니다.

즉, 동일한 배열입니다. 그리고 전에 arr이 가리키던 배열은 더 이상 사용할 수가 없습니다.


다음은 이에 대한 예제입니다.


image



for문 대신 System 클래스의 arraycopy()를 사용하면 보다 간단하고 빠르게 배열을 복사할 수 있습니다.

배열의 복사는 for문보다 System.arraycopy()를 사용하는 것이 효율적입니다.


System.arraycopy(복사할 배열 이름,복사할 배열 시작 번지,복사될 배열 이름, 복사될 배열 시작 번지,복사할 배열 요소 개수)



이 때 복사하려는 배열의 위치가 적절하지 못하여 복사하려는 내용보다

여유 공간이 적으면 에러가 발생하므로 조심해야합니다.

다음은 이와 관련된 예제입니다.


image



배열의 응용



다음은 배열을 이용한 예제들입니다.


image




image