Array는 변경이 가능하고 값에 인덱스를 가진 컬렉션이다.
배열은 랜덤 접근에 대해 Vector 대비 실제로 상수 시간의 복잡도를 제공한다. 하지만, Vector에 반해 Array는 메모리의 단일 및 연속 덩어리로 한 번에 할당된다. 그리고, Array는 엘리먼트의 앞과 뒤에 추가할 수 있는 오퍼레이션을 지원하지 않는다.
scala의 Array는 java Array를 활용한 방식을 사용하고 있다. 그럼에도 불구하고 성능이 좋다. 추가 기능이 없지만, 상황에 따라서 Vector보다 더 좋을 수 있다.
http://docs.scala-lang.org/overviews/collections/performance-characteristics.html
| head | tail | apply | update | prepend | append | insert |
---|
Array에 대한 간단한 예시이다.
var crew = Array("John","Samuel","Matt")
crew(0) = "Juno"
for (c <- crew) {
print(c + " ")
}
println()
Predef
var student = new Array[String](5)
student = crew
for (s <- student) {
print(s + " ")
}
println
결과는 다음과 같다.
Juno Samuel Matt
Juno Samuel Matt
특이할 점은 Array는 implicit을 잘 활용한다. Array와 WrappedArray가 되었다.
scala> val a = Array(1, 2, 3, 4, 5)
a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> val b:Seq[Int] = a
b: Seq[Int] = WrappedArray(1, 2, 3, 4, 5)
WrappedArray는 Array로 돌릴 수 있다.
scala> val c = b.toArray
c: Array[Int] = Array(1, 2, 3, 4, 5)
그리고, 처음 배열과 비교해 본다. 동일한 값이다!
scala> a==c
res3: Boolean = true
이제 Array.reverse 메소드를 적용해보자. Array는 reverse 되어도 Array타입이 되고, 6을 추가할 수 있다.
scala> a.reverse
res4: Array[Int] = Array(5, 4, 3, 2, 1)
scala> a :+ 6
res5: Array[Int] = Array(1, 2, 3, 4, 5, 6)
WrappedArray.reverse 메소드를 적용하자. WrappedArray를 reverse하면 WrappedArray 타입이 되는데, 6을 추가할 수 있다. 하지만, 타입이 ArrayBuffer로 바뀌었다. ( Seq임을 잘 살펴본다)
scala> b.reverse
res6: Seq[Int] = WrappedArray(5, 4, 3, 2, 1)
scala> b :+ 6
res7: Seq[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)
implicit이 발생한 것이다.
WrappedArray의 선언을 살펴보자.
* A class representing `Array[T]`.
*
* @tparam T type of the elements in this wrapped array.
*
abstract class WrappedArray[T]
extends AbstractSeq[T]
with IndexedSeq[T]
with ArrayLike[T, WrappedArray[T]]
with CustomParallelizable[T, ParArray[T]]
..
Predef 에 보면, Array에 대한 implicit 함수가 있는 것이 눈에 보인다..
implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = {
if (xs eq null) null
else if (xs.length == 0) WrappedArray.empty[T]
else new WrappedArray.ofRef[T](xs)
}
implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null
implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null
implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null
implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null
implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null
implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null
implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null
implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null
implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null
Array를 사용할 때, 다른 스칼라 컬렉션에서 사용 가능한 대부분의 메소드를 사용할 수 있다.
implicit 변환은 Array을 ArrayOps와 WrappedArray를 확대하는데 사용된다. ArrayOps은 Array에 대한 간단한 래퍼 클래스이다.
ArrayOps는 임시로 Array에 인덱스를 가진 순서 집합에서 찾을 수 있는 모든 오퍼레이션을 사용할 수 있게 해주는 간단한 Array 래퍼 클래스이다.
ArrayOps의 메소드를 호출하면 Array를 리턴한다.