Array란 무엇인가?
Array는 메모리의 연속적인 공간을 차지하고 있는 정적인 자료구조이다. 이러한 특성으로 인해 Array는 생성 시 크기를 지정해야 하며, 생성한 이후에는 크기의 조절이 불가능하다.
Array의 특징
위의 특성으로부터 Array의 여러가지 특성이 나오는데, 아래 두 가지가 대표적인 특성이다.
1. Array는 Random access가 가능해 검색 속도가 빠르다.
Array는 연속적인 공간을 차지하고 있으므로, Index를 이용해 객체로의 빠른 접근이 가능하다.
2. Array 생성 후에는 크기 조절이 불가능하다.
Array는 메모리의 연속적인 공간을 차지하고 있어 일부를 제외하거나 공간을 추가하는 크기 조절이 불가능하다.
Array의 크기 조절
Array에 값을 추가하려면(=크기를 조절하려면) 새로운 Array를 만들어 추가하려는 값과 함께 이전 Array의 값들을 복사 붙여넣기 하는 수 밖에 없다. 즉, 이미 생성된 Array를 사용하는 것이 아닌 새로운 Array를 만들어 내야 하는 것이다. 이러한 특성을 잘 기억해두고 아래에서 Array를 어떻게 생성하고 조작하는지 알아보자.
Array의 생성
Array는 연속적인 메모리 공간을 차지하기 때문에, Array를 생성하기 위해서는 크기 값이 정해져 있어야 한다. 크기 값은 암시적으로 혹은 명시적으로 지정될 수 있다. 아래에서 Array를 만드는 다양한 메서드를 살펴보자.
arrayOf(vararg elements : T)
값을 직접 입력하여 배열 생성한다. Array의 크기가 입력된 값에 따라 정해진다.
val array: Array<Int> = arrayOf(1, 2, 3) // {1, 2, 3} 생성
arrayOfNulls(size : Int)
Array의 크기 값(size)을 지정해주면 그만큼 null이 들어간 배열을 반환한다.
val arrOfNulls : Array<Int?> = arrayOfNulls<Int>(3) // {null, null, null} 생성
emptyArray()
크기가 0인 Array를 생성한다. 이 Array에는 아무런 값도 들어가 있지 않다. 실무에서 Default 값으로 자주 사용된다.
val emptyArray : Array<Int> = emptyArray() // {}생성
Array(size: Int, init: (Int) -> T)
Lambda를 사용하여 Array를 생성할 수 있다. IntArray와 같은 Primitive Type Array도 같은 방식으로 생성 가능하다. Array의 생성자를 이용해 생성하는 방식이다.
val arrayLambda: Array<Int> = Array(5) { index -> index } // {0, 1, 2, 3, 4} 생성
val intArrayLambda : IntArray = IntArray(5){ index -> index } // {0, 1, 2, 3, 4} 생성
IntRange를 이용하여 Array생성
IntRange는 바로 Array로 변환하지 못하므로 List로 변환 후에 Array로 변환시켜야한다. Primitive Type Array도 같은 방식으로 생성 가능하다.
val intArrayWithRange: Array<Int> = (0..10).toList().toTypedArray() // {0, 1, 2 .. 9}생성
val intArrayWithRange: IntArray = (0..10).toList().toIntArray() // {0, 1, 2 .. 9}생성
Array의 값에 접근하고 변경하기
Array는 Random Access가 가능한 자료구조이다. 따라서 Index를 이용하여 직접 자료에 접근하고 변경하는 것이 가능하다. 값이 변경 하다는 것은 값을 추가하거나 제거한다는 의미가 아닌, 이미 짜여진 메모리 공간의 값을 바꾼다는 뜻이다.
Index를 이용한 값 접근 및 변경
0번부터 시작되는 index를 이용해 값의 접근 이 가능하며, 같은 방법으로 값에 접근하여 = 연산자를 이용하여 값의 변경이 가능하다.
val arrayExample: Array<String> = arrayOf("a", "b", "c")
/* 대괄호 [index]를 이용하여 접근 */
print(arrayExample[1]) // b
arrayExample[1] = "c"
print(arrayExample[1]) // c
/* get,set 메서드를 사용하여 값 접근 및 변경 */
print(arrayExample.get(1)) // b
arrayExample.set(1, "c")
n차원 배열 값 접근 및 변경
n차원 배열도 마찬가지이다. n차원 배열은 Array 안에 Array가 들어있는 형태이다. 예를 들어 2차원 배열은 바깥 Array에 대해 안쪽 Array들이 존재하는 구조이다. 2차원 배열에 접근하기 위해서는 바깥쪽으로부터 몇번째 Array인지 확인하여 index로 접근하고, 그 내부의 원소에 대해 index를 이용하여 다시 접근하면 된다.
val arrayExample: Array<Array<String>> = arrayOf(arrayOf("a", "b", "c"), arrayOf("e", "f"))
print(arrayExample[0][1]) // b
arrayExample[0][1] = "g"
print(arrayExample[0][1]) // g
*주의할 것은 내부의 Array의 원소 개수가 꼭 일치할 필요는 없는 것이다. Array를 행렬로 쓰는 경우가 많은데, 행렬로 쓰지 않아도 무방하며, 꼭 원소의 개수는 일치할 필요가 없다.
arrayExample[0] // {"a", "b", "c"}
arrayExample[1] // {"e", "f"}