2012-05-21 3 views
2

Map()에 대한 표준 호출로 불변의 맵을 만들거나 이와 같이 작성된 기존 맵을 연결하여 모든 테스트에서 해당 멤버를 순회하면 추가 순서대로 제공됩니다. 그것이 꼭 필요한 정렬 방법이지만, 맵 멤버의 순서의 신뢰성에 대한 문서에는 단어가 없습니다.맵 멤버의 순서가 추가되고 신뢰성이있는 것처럼 보입니까?

표준 맵이 추가 순서로 항목을 반환 할 것이라고 기대하는 것이 안전한지, 아니면 다른 구현과 그 경우 어떤 것을 찾아야하는지 궁금합니다.

+0

일반적으로 구현 세부 정보를 사용하는 것은 바람직하지 않습니다. 즉,'scala.collection.immutable.Map [A, B]'는 순서를 보장하는'Seq [(A, B)]'가 아닌'Iterable [(A, B)]'를 구현합니다. – ziggystar

+0

'Map [K, V]'대신'Map [K, (V, Int)]'를 사용할 수 있습니다. 그런 다음 모든 쌍을 시퀀스로 추출해야하는 경우'toSeq'를 호출하고 해당 필드를 정렬하십시오. –

답변

5

나는 그것이 안전하다고 생각하지 않는다, 순서는 5 개 요소 (스칼라 2.9.1)에서 시작하여 보존되지 않습니다 : 더 큰 주문을지도에서

scala> Map(1 -> 1, 2 -> 2, 3 -> 3, 4 -> 4, 5 -> 5) 
res9: scala.collection.immutable.Map[Int,Int] = 
    Map(5 -> 5, 1 -> 1, 2 -> 2, 3 -> 3, 4 -> 4) 

완전히 "랜덤"되어, Map((1 to 100) zip (1 to 100): _*)을 시도합니다.

정렬 된 항목의 경우 LinkedHashMap을, 정렬 된 항목의 경우 TreeMap을 시도하십시오.

+0

Yikes! 같은 것을 2.10.0-M3에서 재생성 할 수 있습니다. 좋아, 질문의 두 번째 부분 : 어떤 구현을 권하고 싶습니다. –

+0

@NikitaVolkov : 정렬 된 항목은 ['LinkedHashMap'] (http : //www.scala-lang.org/api/current/scala/collection/mutable/LinkedHashMap.html) /www.scala-lang.org/api/current/scala/collection/immutable/TreeMap.html) 정렬 된 항목을 얻을 수 있습니다. –

+0

고마워,하지만'LinkedHashMap'은 항목을 올바르게 정렬 할 수 있지만 그것은 바뀔 수있다. 나는 또한 트릭을 수행하지만 [this] (http://www.scala-lang.org/docu/files/collections-api/collections_40.html)에 따르면 그것은 지독하게 수행 할 수없는 불변의 ListMap을 안다. 내가 처리해야하거나 맞춤 구현을하는 것처럼 보입니다 - 맞습니까? –

1

Map의 주문에 대한 약속은 없습니다. scalas 컬렉션 패키지에는 OrderedMap이 있습니다. 해당 패키지의 값은 내재 된 Ordering에 의해 정렬됩니다. quickfix로 맵의 순서에 키 목록을 사용하는 것이 좋습니다.

var keyOrdering = List[Int]() 
var unorderedMap = Map[Int, String]() 

unorderedMap += (1 -> "one") 
keyOrdering :+= 1 

당신은 Ordering 자신의 구현뿐만 아니라 SortedMap에 전달할 수

편집.

편집 # 2

간단한 예는 다음과 같습니다

scala> import scala.collection.SortedMap 
import scala.collection.SortedMap 

scala> implicit object IntOrdering extends Ordering[Int] 
    | def compare(a: Int, b: Int) = b - a 
    | } 
defined module IntOrdering 

scala> var sm = SortedMap[Int, String]() 
sm: scala.collection.SortedMap[Int,String] = Map() 

scala> sm += (1 -> "one") 

scala> sm += (2 -> "two") 

scala> println(sm) 
Map(2 -> two, 1 -> one) 

내재 된 주문은 키에 적용되기 때문에 IntOrderingSortedMap[Int, Any]에 적용 할 수 있습니다.

편집 # 3

내 댓글이 방법으로 보일 수 있습니다에 같은 자기 순서 데이터 형식 : I 희망

implicit object DataTypeOrdering extends Ordering[DataType[_]] { 
    def compare(a: DataType[_], b: DataType[_]) = a.index - b.index 
} 

:

case class DataType[T](t: T, index: Int) 
object DataType{ 
    private var index = -1 
    def apply[T](t: T) = { index += 1 ; new DataType[T](t, index) 
} 

지금 우리는 주문을 변경해야을 이것이 당신이 내 대답을 기대했던 방식입니다.

+1

'Ordering'과'SortedMap'에 대해 좀 더 자세히 설명해 주시겠습니까? –

+0

간단한 답변으로 답변을 업데이트했습니다. –

+0

감사합니다.하지만 잘못된 것입니다 : 두 예제 모두에서 누적 순서가 아닌 키별로 맵을 정렬합니다. –

1

파기 한 후에 정확히 원하는대로 동작하는 불변의 ListMap이 있다는 것을 알았지 만 this table에 따르면 그 성능은 아주 끔찍합니다. 그래서 선형 적으로 수행하는 제거를 제외한 모든 작업에서 효과적으로 수행해야하는 사용자 지정 불변 구현을 작성했습니다. 그것은 표준 MapQueue에 의해 뒷받침되기 때문에 조금 더 많은 메모리가 필요합니다. 그 자체는 List을 두 번 사용하지만, 현재의 시대에는 문제가되지 않습니다.

import collection.immutable.Queue 

object OrderedMap { 
    def apply[A, B](elems: (A, B)*) = 
    new OrderedMap(Map(elems: _*), Queue(elems: _*)) 
} 
class OrderedMap[A, B](
    map: Map[A, B] = Map[A, B](), 
    protected val queue: Queue[(A, B)] = Queue() 
) extends Map[A, B] { 
    def get(key: A) = 
    map.get(key) 
    def iterator = 
    queue.iterator 
    def +[B1 >: B](kv: (A, B1)) = 
    new OrderedMap(
     map + kv, 
     queue enqueue kv 
    ) 
    def -(key: A) = 
    new OrderedMap(
     map - key, 
     queue filter (_._1 != key) 
    ) 
    override def hashCode() = 
    queue.hashCode 
    override def equals(that: Any) = 
    that match { 
     case that: OrderedMap[A, B] => 
     queue.equals(that.queue) 
     case _ => 
     super.equals(that) 
    } 
} 
관련 문제