为什么可变和不可变的ListMaps在Scala中有不同的订单?

为什么不可变版的ListMap存储升序,而可变版本按降序存储?

这是一个测试,您可以使用,如果你有scalatest-1.6.1.jar和junit-4.9.jar

@Test def StackoverflowQuestion()
  {
    val map = Map("A" -> 5,"B" -> 12,"C" -> 2,"D" -> 9,"E" -> 18)
    val sortedIMMUTABLEMap = collection.immutable.ListMap[String,Int](map.toList.sortBy[Int](_._2): _*)
    println("head : " + sortedIMMUTABLEMap.head._2)
    println("last : " + sortedIMMUTABLEMap.last._2)
    sortedIMMUTABLEMap.foreach(X => println(X))
    assert(sortedIMMUTABLEMap.head._2 < sortedIMMUTABLEMap.last._2)

    val sortedMUTABLEMap = collection.mutable.ListMap[String,Int](map.toList.sortBy[Int](_._2): _*)
    println("head : " + sortedMUTABLEMap.head._2)
    println("last : " + sortedMUTABLEMap.last._2)
    sortedMUTABLEMap.foreach(X => println(X))
    assert(sortedMUTABLEMap.head._2 > sortedMUTABLEMap.last._2)
  }

接受PASSING测试的输出

head : 2
last : 18
(C,2)
(A,5)
(D,9)
(B,12)
(E,18)
head : 18
last : 2
(E,18)
(B,12)
(D,9)
(A,5)
(C,2)

解决方法

症状可以简化为:

scala> collection.mutable.ListMap(1 -> "one",2 -> "two").foreach(println)
(2,two)
(1,one)

scala> collection.immutable.ListMap(1 -> "one",2 -> "two").foreach(println)
(1,one)
(2,two)

您的代码中的“排序”不是问题的核心,您对ListMap的调用是使用来自构造由可变或不可变列表支持的列表映射的协同对象的ListMap.apply调用.规则是插入顺序将被保留.

差异似乎是可变列表由不可变列表支持,插入发生在前面.所以这就是为什么当迭代你得到LIFO行为.我还在看着这个不变的,但是我敢打赌,这些插入是有效的在后面.编辑,我改变主意:insert可能在前面,但似乎immutable.ListMap.iterator方法决定在返回的迭代器上使用一个toList.reverseIterator来反转结果.我认为它值得把它放在邮件列表中.

文件可以更好吗?当然.有疼吗不是真的,我不会让它发生.如果文档不完整,在选择结构与另一个结构之前,测试行为或去查找源是明智的.

实际上,如果Scala团队决定在以后改变行为,感觉可以因为行为无效,没有合同,那么可能会有痛苦.

为了解决您在评论中解释的用例,您已经收集了地图中的字符串频率计数(可变或不可变):

val map = Map("A" -> 5,"E" -> 18,"B" -> 5)

由于您最终只需要排序一次,所以您可以将元组从地图转换为seq,然后排序:

map.toSeq.sortBy(_._2)
// Seq[(java.lang.String,Int)] = ArrayBuffer((C,2),(A,5),(B,(D,9),(E,18))

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...