원문: Mutable and Immutable Collections
Scala 컬렉션은 시스템적으로 변경 가능한 컬렉션과 변경 불가능한 컬렉션을 구분합니다. 변경 가능한 컬렉션은 현재 위치에서 업데이트되거나 확장될 수 있습니다. 즉, 컬렉션의 요소를 변경하거나 추가하거나 제거하는 작업을 부수 효과로서 이룰 수 있습니다. 반면에, 변경 불가능한 컬렉션은 절대로 변하지 않습니다. 당신에게는 요소를 추가하거나 제거 또는 갱신하는 연산이 주어지지만, 이러한 연산은 항상 새로운 컬렉션을 반환하고 기존의 컬렉션은 변하지 않은 채로 유지시킵니다.
모든 컬렉션 클래스는 scala.collection 패키지 또는 이의 하위 패키지인 mutable, immutable, generic 패키지에 위치해 있습니다. 대부분의 컬렉션 클래스들은 세 가지 변형(variants)이 있으며, 각각 scala.collection, scala.collection.immutable, scala.collection.mutable 패키지에 존재합니다. 각 변형은 변경 가능성에 따라 다른 특성을 가집니다.
scala.collection.immutable 패키지에 있는 컬렉션은 모든 사용자에게 변경 불가능하다는 것이 보장됩니다. 이러한 컬렉션은 생성된 후에는 절대로 변하지 않습니다. 따라서 동일한 컬렉션 값을 여러 시점에 반복해서 접근해도 항상 동일한 요소를 가진 컬렉션을 얻을 수 있습니다.
scala.collection.mutable 패키지에 있는 컬렉션은 현재 위치에서 컬렉션을 변경하는 일부 연산을 포함하는 것으로 알려져 있습니다. 따라서 변경 가능한 컬렉션을 다룰 때는 어떤 코드가 어느 시점에 어떤 컬렉션을 변경하는지 이해해야 합니다.
scala.collection 패키지의 컬렉션은 변경 가능할 수도 있고, 변경 불가능할 수도 있습니다. 예를 들어, collection.IndexedSeq[T]는 collection.immutable.IndexedSeq[T]와 collection.mutable.IndexedSeq[T]의 상위 클래스입니다. 일반적으로 scala.collection 패키지의 루트 컬렉션은 변경 불가능한 컬렉션과 동일한 인터페이스를 정의하며, scala.collection.mutable 패키지의 변경 가능한 컬렉션은 이 불변 인터페이스에 일부 부수 효과가 있는 수정 연산을 추가합니다.
루트 컬렉션과 변경 불가능한 컬렉션의 차이점은, 변경 불가능한 컬렉션의 사용자는 누구도 그 컬렉션을 변경할 수 없다는 보장을 받는 반면, 루트 컬렉션의 사용자는 자신이 그 컬렉션을 변경하지 않는다고 약속한다는 것 뿐입니다. 비록 그러한 컬렉션의 정적 타입이 컬렉션을 수정하는 연산을 제공하지 않는다 하더라도, 실행 시점의 타입이 변경 가능한 컬렉션일 경우 다른 클라이언트가 그 컬렉션을 변경할 수 있습니다.
기본적으로 Scala는 항상 변경 불가능한 컬렉션을 선택합니다. 예를 들어, 아무 접두사 없이 Set을 작성하거나 다른 곳에서 Set을 임포트하지 않는다면 변경 불가능한 집합을 얻게 되고, Iterable을 작성하면 변경 불가능한 Iterable 컬렉션을 얻게 됩니다. 이들이 Scala 패키지에서 기본적으로 가져오는 바인딩이기 때문입니다. 만약 기본적으로 변경 가능한 버전을 사용하고 싶다면 collection.mutable.Set 또는 collection.mutable.Iterable을 명시적으로 작성해야 합니다.
변경 가능한 버전과 변경 불가능한 버전을 모두 사용하고 싶을 때 유용한 관례는 collection.mutable 패키지만 가져오는 것입니다. (effective-scala에도 나와있습니다)
import scala.collection.mutable
이렇게 하면 접두사 없는 Set과 같은 단어는 여전히 변경 불가능한 컬렉션을 의미하지만, mutable.Set은 변경 가능한 대응 객체를 나타냅니다.
컬렉션 계층 구조에서 마지막 패키지는 collection.generic입니다. 이 패키지에는 컬렉션을 구현하기 위한 기본 요소들이 포함되어 있습니다. 일반적으로 컬렉션 클래스는 일부 연산의 구현을 generic 패키지의 클래스에 위임합니다. 그러나 컬렉션 프레임워크의 사용자는 예외적인 경우에만 generic 패키지의 클래스를 참조할 필요가 있습니다.
편의성과 하위 호환성을 위해 몇 가지 중요한 타입들은 scala 패키지에 별칭(alias)으로 정의되어 있어서, import 없이 간단한 이름으로 사용할 수 있습니다. 예를 들어, List 타입은 다음과 같이 접근할 수 있습니다.
- scala.collection.immutable.List : List가 정의되어 있는 곳입니다.
- scala.List : scala 패키지에 정의된 별칭입니다.
- List : scala_가 항상 임포트되어 있기 때문에 바로 접근이 가능합니다.
다른 별칭으로 제공되는 타입에는 Traversable, Iterable, Seq, IndexedSeq, Iterator, Stream, Vector, StringBuilder, Range가 포함됩니다.
다음 그림은 scala.collection 패키지의 모든 컬렉션을 보여줍니다. 이들은 모두 고수준의 추상 클래스나 트레이트이며, 일반적으로 변경 가능한 구현과 변경 불가능한 구현을 모두 가지고 있습니다.
다음 그림은 scala.collection.immutable 패키지의 모든 컬렉션을 보여줍니다.
다음 그림은 scala.collection.mutable 패키지의 모든 컬렉션을 보여줍니다.
(위의 그림은 모두 Matthias가 decodified.com 에서 생성한것입니다.)