Arrays
[Java강의노트] 배열
배열
배열의 선언과 할당
학생들의 점수를 저장한다고 했을 때 각 학생들의 점수를 일일이 변수를 선언하여 저장한다면 여러모로 불편할 것입니다.
class Hackjum1 { public static void main(String[] args) { int cheulYee = 80; int youngHyee = 90; int baDookYee = 100; int sum = cheulYee + youngHyee + baDookYee; System.out.println(sum); } }
만일 학생이 30명이라면 30개의 변수를 선언해야 하고 합계를 구하기 위해 30개의 변수를 나열해야하므로 코드는 악몽이 되어버릴 것입니다. 배열은 이와 같이 같은 타입의 데이터를 모아서 번호를 붙여서 처리하는 방식입니다.
class Hackjum2 { public static void main(String[] args) { int[] hackjum = new int[3]; hackjum[0] = 80; hackjum[1] = 90; hackjum[2] = 100; int sum = 0; for (int i : hackjum) { sum += i; } System.out.println(sum); } }
배열은 다음과 같이 사용합니다.
배열 선언 : 배열을 가리키는 참조 변수를 선언하는 것으로 배열의 타입을 '[]'과 함께 선언한다.
int[] i; int i[]; // 두 표현은 동일한 표현이다.
배열 할당 : 선언된 참조 변수에 배열 인스턴스(객체)를 할당한다. new 연산자를 이용하여 배열 인스턴스를 생성하며 이때 배열의 크기를 지정한다.
i = new int[30];
배열 초기화 : 선언된 배열의 각 요소에 초기값을 할당하는 단계로 배열 참조 변수에 초기값을 할당하는 것으로 배열 할당을 한꺼번에 처리할 수 있다.
i[0] = 0; i[1] = 1; ... i[29] = 29; i = new int[]{0, 1, ..., 29}; i = {0, 1, 2, ..., 29}; // 배열의 초기값을 {}연산자로 할당하여 초기값을 이용하여 배열 인스턴스를 할당할 수 있다.
배열의 각 요소는 인덱스를 통해 접근하며 인덱스는 반드시 0부터 시작한다.
기본형 배열과 참조형 배열
배열은 동일한 타입의 요소들을 하나의 통일된 변수 이름과 인덱스를 이용하여 for 문등과 함께 사용하면 모든 요소를 대상으로 한 작업을 손쉽게 해낼 수 있습니다. 배열의 요소는 기본 데이터 타입뿐만 아니라 객체 타입도 사용할 수 있습니다.
MyClass[] my = new MyClas[30]; // MyClass 타입의 참조 변수를 30개 생성한다. my[0] = new MyClass(); // 배열의 각 요소에 MyClass 인스턴스를 할당한다.
개선된 for 문의 사용
일반적으로 배열의 각 요소로 접근하기 위해서 인덱스를 사용하며 for문을 이용하여 배열의 각 요소를 처리할 수 있습니다.
for (int i = 0; i < array.length; i++) { System.out.println(array[i]); }
자바 5.0부터는 for-each문이라는 새로운 형태의 구문을 제공합니다. 그러나 이 경우 인덱스를 이용한 배열에 대한 직접 접근이 불가능하여 요소의 변경 작업을 할 수 없습니다. 결국 요소의 변경 작업을 위해서는 기존 for문을 사용해야 합니다.
for (int e : array) { System.out.println(e); }
다차원 배열
배열에 저장된 요소가 배열인 경우 다차원 배열이라고 하며 차원의 증가는 로직의 복잡성을 증가시키므로 2차원 이상의 배열 사용은 권장되지 않습니다.
고정 길이 배열
int[][] array; array = new int[2][3]; array[0][0] = 1; array[0][1] = 2; ... array[1][0] = 4; ... array[1][2] = 6; for (int i = 0; i < 2; i++) for (int j = 0; j < 3; j++) System.out.println(array[i][j]);
배열은 총 2 x 3개의 요소를 가지며 2차원 배열로 2개의 인덱스를 사용한다.
가변 길이 배열
int[][] array; array[0] = new int[10]; array[1] = new int[5]; for (int i = 0; i < array.length; i++) for (int j = 0; j < array[i].length; j++) System.out.println(array[i][j]);
배열은 10개의 요소와 5개의 요소를 갖는 가변 길이로 선언된다. 배열의 각 요소에 대한 접근을 위해 i번째 배열의 크기를 저장하고 있는 length 속성을 사용한다.
배열의 조작(java.util.Arrays)
배열의 복사
자바 표준 라이브러리에는 배열의 복사를 위해 System.arrayCopy()라는 static 메서드가 있습니다. 배열을 직접 for문을 이용하여 복사하는 것보다 성능이 뛰어난 메서드입니다. 원본 배열의 요소를 원하는 만큼만 복사본으로 지정된 위치에 복사할 수 있습니다.
class ArrayCopyEx { public static void main(String[] args) { byte[] ar1 = {11, 22, 33, 44, 55}; byte[] ar2 = new byte[10]; System.arraycopy(ar1, 0, ar2, 3, 5); System.out.println("::::: 원본 배열 :::::"); for (byte n : ar1) System.out.println(n); System.out.println("::::: 복사본 배열 :::::"); for (byte n : ar2) System.out.println(n); } }
또한 java.util.Arrays 클래스에서 제공되는 copyOf() 메서드 또한 배열의 복사를 위해 사용할 수 있습니다. System.arrayCoyp()와 달리 원본과 동일 구조로 배열을 복사합니다.
import java.util.Arrays; class ArrayCopyEx2 { public static void main(String[] args) { byte[] ar1 = {11, 22, 33, 44, 55}; byte[] ar2; ar2 = Arrays.copyOf(ar1, 5); System.out.println("::::: 원본 배열 :::::"); System.out.println("배열의 크기 : " + ar1.length); for (byte n : ar1) System.out.println(n); System.out.println("::::: 복사본 배열 :::::"); System.out.println("배열의 크기 : " + ar2.length); for (byte n : ar2) System.out.println(n); } }
배열 비교하기
java.util.Arrays 클래스는 기본형 및 객체형 배열간을 비교하기 위하여 equals() 메서드를 제공합니다. 객체형 배열의 경우 사용자 정의형의 경우 Object.equals() 메서드를 오버라이딩하여야 합니다.
import java.util.Arrays; class ArrayCompEx1 { public static void main(String[] args) { int[] ar1 = new int[10]; int[] ar2 = new int[10]; Arrays.fill(ar1, 10); Arrays.fill(ar2, 10); System.out.println(Arrays.equals(ar1, ar2)); ar1[3] = 15; System.out.println(Arrays.equals(ar1, ar2)); } }
배열 요소의 정렬
Arrays.sort() 메서드는 배열내 요소의 타입을 기반으로 비교를 하여 정렬을 수행합니다. 기본형이 아닌 사용자 정의 타입의 경우 java.lang.Comparable 인터페이스의 compareTo() 메서드를 구현한 클래스를 만들고 Arrays.sort() 메서드를 실행하여 정렬할 수 있습니다.
package net.jeongsam.examples; import java.util.Arrays; class ArraySortEx1 implements Comparable{ int i; public ArraySortEx1() { } public ArraySortEx1(int i) { this.i = i; } /** * comparaTo() 메서드는 동일한 타입의 다른 객체를 인자로 하여 * 현재 객체가 인자 객체보다 작으면 음수 값을 리턴하고 동일하면 0을 크면 1을 리턴한다. */ @Override public int compareTo(ArraySortEx1 obj) { return ((i < obj.i) ? -1 : ((i == obj.i) ? 0 : 1)); } public static void main(String[] args) { ArraySortEx1[] array = {new ArraySortEx1(11), new ArraySortEx1(5), new ArraySortEx1(9), new ArraySortEx1(10), new ArraySortEx1(1)}; System.out.println("정렬전"); for (ArraySortEx1 e : array) System.out.print(e.i + " "); System.out.println(); Arrays.sort(array); System.out.println("정렬후"); for (ArraySortEx1 e : array) System.out.print(e.i + " "); System.out.println(); } }
문자열 배열의 정렬은 사전식 정렬을 하며 콤퍼레이터(Comparator)를 사용하여 대소문자 구분없이 정렬이 가능하도록 할 수 있습니다.
import java.util.Arrays; class ArraySortEx2 { public static void main(String[] args) { String[] array = {"bbc", "Abc", "cBC"}; /* 콤퍼레이터 CASE_INSENSITIVE_ORDER를 사용하여 대소문자 구분하지 않고 정렬 */ Arrays.sort(array, String.CASE_INSENSITIVE_ORDER); for (String s : array) System.out.print(s + " "); System.out.println(); } }