본문 바로가기

JAVA

자바 기초부터 차근차근...(13)

※ Chapter13 배열
※ 본문은 윤성우의 열혈JAVA를 정리한 글입니다. 
※ 문제가 될시 비공개 처리하겠습니다.


§ 1차원 배열의 이해와 활용

 

■ 1차원 배열의 생성 방법

 

1차원 배열은 다음과 같이 정의할 수 있다.

"타입이 같은 둘 이상의 데이터를 저장할 수 있는 1차원 구조의 메모리 공간"

'자바에서는 배열도 인스턴스'이다.

int[] ref = new int[5]; //길이가 5인 int형 1차원 배열의 생성문

 

int[] ref -> int형 1차원 배열 인스턴스를 참조할 수 있는 '참조변수 선언'

new int[5] -> int형 값 5개를 저장할 수 있는 '배열 인스턴스 생성'

 

int[] ref;

ref = new int[5]; // 이런식으로도 선언 가능

 

예제를 통해서 '배열이 인스턴스'임을 보자.

이 예제에서는 배열의 인스턴스 변수 length에 접근하여 길이 정보를 출력하였다.

인스턴스 변수에 접근 가능하다는 것 = 배열이 인스턴스이다. 라고 볼 수 있다.

 

다음 예제를 보면 알수 있는데, 인스턴스를 저장할 수 있는 배열의 생성도 가능하다.

여기서 주의할 사실은 다음과 같다.

"이는 codema 인스턴스 5개를 저장할 수 있는 참조변수의 배열이다."

 

codema 인스턴스의 생성과는 관계가 없다. 배열이 생성될 뿐이다.

 

■ 배열을 대상으로 한 값의 저장과 참조

 

int[] ar = new int[3];

이 배열의 첫 번째 공간에 값을 저장하는 방법은 다음과 같다.

ar[0] = 7; //인덱스 값이 0부터 시작한다는 것을 알아두자.

 

이와 관련하여 위의 예제를 변경해서 확인해보자.

 

String형 배열에 문자열을 저장하고 참조하는 코드를 보자.

반복문을 이용해서 String 인스턴스의 length 메소드를 순차적으로 호출할 수 있음을

확인할 수 있다.

 

■ 배열을 생성과 동시에 초기화하기

 

int[] arr = new int[3];

 

동시에 초기화 하려면 다음과 같이 진행하면 된다.

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

배열의 길이는 초기화와 동시에 진행되므로 생략해야 한다. 안그러면 컴파일 오류남 주의.

 

이 문장을 다음과 같이 줄여서 표현도 가능하다.

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

 

또한 int[] ar = new int[3]; 과 int ar[] = new int[3]; 둘다 가능하니 알아두자. (앞의 것을 더 선호함)

 

■ 배열의 참조 값과 메소드

 

배열도 인스턴스이므로 메소드 호출 시 참조 값의 전달이 가능하다.

예를 들어서 다음과 같이 배열의 참조 값을 인자로 전달할 수 있다.

 

public static void main(String[] args) {

     int[] ar = {1, 2, 3, 4, 5, 6, 7};

     int sum = sumOfAry(ar);

...}

그리고 다음과 같이 메소드를 정의해야 한다 .(호출한 메소드)

static int sumOfAry(int[] ar) {

     int sum = 0;

     for(int i = 0; i < ar.length; i++)

          sum+= ar[i];

     return sum;

}

 

그리고 다음과 같이 배열의 참조 값을 반환하는 메소드를 정의하는 것도 가능하다.

static int[] makeNewIntAry(int len) {

     int[] ar = new int[len];

     return ar;

}

 

■ 배열의 초기화와 배열의 복사

 

배열이 생성되면 모든 요소는 0 또는 null값으로 초기화된다. 

int[] ar = new int[10]; // 배열의 모든 요소 0으로 초기화

String[] ar = new String[10]; // 배열의 모든 요소 null로 초기화

 

그러나 0 이외의 값으로 초기화해야 할 때가 있다. 이러한 경우

반복문을 사용할 수도 있지만 다음과 같은 메소드 호출을 통해 원하는 값을 저장할 수도 있다.

 

public static void fill(int[] a, int val) -> 두 번째 인자로 전달된 값으로 배열 초기화

public static void fill(int[] a, int fromIndex, int toIndex, int val) -> 인덱스 범위까지 val 값으로 초기화

 

위의 메소드들은 java.util.Arrays 클래스에 정의되어 있으며 각 기본 자료형 별로 메소드가

오버로딩 되어 있다. 

 

배열을 복사해야 하는 상황도 발생하는데, 이 경우에도 java.lang.System 클래스의 메소드를 통해

복사를 진행할 수 있다. (물론 반복문으로도 가능하다)

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

-> 복사 원본의 위치 : 배열 src의 인덱스  srcPos

-> 복사 대상의 위치 : 배열 dest의 인덱스 destPos

-> 복사할 요소의 수 : length

 

위의 메소드를 예제로 알아보자.

 

■ main 메소드의 매개변수 선언

 

이제는 다음 main 메소드의 매개변수 선언이 무엇을 의미하는지 이해할 수 있다.

public static void main(String[] args) {...}

 

매개변수로 String 배열의 참조변수가 선언되었다. 따라서 다음과 같이 호출해야 한다

String[] arr = new String[] {"Coffee", "Milk", "Orange"};

main(arr)

 

물론 이렇게 호출하진 않는다. 

String 배열을 구성하는 것도 main 메소드를 호출하는 것도 가상머신에 의해 이뤄지는 일이다.

다만, String 배열을 구성할 문자열은 프로그램 사용자가 전달해야 한다.

예를 들어서 Simple.class에 위치한 main 메소드를 다음과 같이 호출한다고 가정해보자

 

C :\JavaStudy>java Simple

그러면 String 배열이 다음과 같이 구성이 되어 main 메소드에 전달이 된다.

String[] arr = new String[] {};

즉, 빈 String 배열이 생성되어 main 메소드의 호출이 이뤄진다. 반면 다음과 같이 실행하면,

C:\JavaStudy>java Simple Coffee Milk Orange

 

String[] arr = new String[] {"Coffee","Milk", "Orange"}; 이렇게 구성되어 전달된다.

 

실행 명령문에 이어서 공백을 구분 기준으로 문자열을 입력하면, 이 내용을 대상으로

String 배열이 구성되고, 이 배열의 참조 값이 전달되면서 main 메소드가 호출이 된다.

 

 

§ enhanced for문 

 

프로그램을 작성하다 보면 다음과 같이 배열에 저장된 모든 요소를 대상으로

연산, 참조, 탐색을 진행하는 경우를 흔히 접할 수 있다. (코딩테스트에서 자주 나옴)

"배열에 저장된 값 중에서 특정 조건에 해당하는 값을 찾아라."

"배열에 저장된 모든 값에 대해 12%씩 그 값을 증가시켜라."

 

이러한 상황에서 문장 구성을 돕기 위해 등장한 것이 enhanced for문이다. (for-each문으로도 불린다.)

"배열에 저장된 모든 값을 출력하라" 는 다음과 같이 작성할 수 있다.

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

for(int i =0; i< ar.length; i++) {

     System.out.println(ar[i]);

}

이는 for문을 enhanced for문으로 다음과 같이 작성한다

for(int e : ar) {

 System.out.println(e);

}

새로운 for문에는 다음 두 가지 장점이 있다.

- 코드의 양이 절대적으로 줄어든다.

- 반복문 구성 과정에서 배열의 길이 정보를 직접 확인하고 입력할 필요가 없다.

for(요소 : 배열) {

     반복 문장

}

 

예제를 보면서 알아보자.

■ 인스턴스 배열을 대상으로 하는 enhanced for문

 

배열에 저장된 내용이 '기본 자료형의 값'이 아닌 '인스턴스의 참조 값'인 경우에도

enhanced for문의 활용에 있어서 달라지는 것은 없다.

Box[] ar = new Box[10];

for(Box e : ar) {

     ...

}

 

예제를 보며 확인해보자.

 

§ 다차원 배열의 이해와 활용

 

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

보통 2차원까지 사용하니 2차원까지만 배워보자(2차원 알면 3차원도 쉬움)

 

■ 2차원 배열의 생성과 접근

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

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

 

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

 

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

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

 

arr[1][0] = 5; 세로, 가로 인덱스 위치가 1,0인 요소에 5를 저장.

 

arr[0][0] arr[0][1] arr[0][2]
arr[1][0] arr[1][1] arr[1][2]
arr[2][0] arr[2][1] arr[2][2]

배열의 접근 방식은 위와 같다.

 

예제를 보면서 다시한번 확인해보자.

 

다음과 같이 활용도 가능하다.

public static void main(String[] args) {

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

     ...

     arr[1] = new int[7] // 두 번째 줄의 배열을 교체하는 문장

     ...

}

이런식으로 되면 arr[1][6] 까지 저장이 가능해지는 배열이 만들어진다.

 

■ 2차원 배열의 초기화

1차원 배열과 마찬가지로 2차원 배열도 생성과 동시에 초기화가 가능하다.

 

바로 예제를 보면서 확인해보도록 하자.(약간의 응용도 들어가 있다.)