'2016/10/29'에 해당되는 글 1건

  1. 2016.10.29 [scala] Array, WrappedArray

[scala] Array, WrappedArray

scala 2016. 10. 29. 07:52


Array는 변경이 가능하고 값에 인덱스를 가진 컬렉션이다. 


배열은 랜덤 접근에 대해 Vector 대비  실제로 상수 시간의 복잡도를 제공한다. 하지만, Vector에 반해 Array는 메모리의 단일 및 연속 덩어리로 한 번에 할당된다. 그리고, Array는 엘리먼트의 앞과 뒤에 추가할 수 있는 오퍼레이션을 지원하지 않는다. 


scala의 Array는 java Array를 활용한 방식을 사용하고 있다. 그럼에도 불구하고 성능이 좋다. 추가 기능이 없지만, 상황에 따라서 Vector보다 더 좋을 수 있다. 



http://docs.scala-lang.org/overviews/collections/performance-characteristics.html


                             headtailapplyupdateprependappendinsert
ArrayCLCC---



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를 리턴한다. 









Posted by '김용환'
,