Zas*_*asz 9 scala scala-collections
为什么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)
}
Run Code Online (Sandbox Code Playgroud)
下面是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)
Run Code Online (Sandbox Code Playgroud)
huy*_*hjl 12
症状可以简化为:
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)
Run Code Online (Sandbox Code Playgroud)
代码中的"排序"不是问题的核心,您的调用ListMap是使用ListMap.apply来自配对对象的调用,该对象构造由可变或不可变列表支持的列表映射.规则是将保留插入顺序.
差异似乎是可变列表由不可变列表支持,插入发生在前面.这就是为什么在迭代时你会得到LIFO行为.我仍然在看不可变的那个,但我敢打赌插入有效地在后面.编辑,我正在改变我的想法:插入可能在前面,但似乎immutable.ListMap.iterator方法决定用toList.reverseIterator返回的迭代器上的结果反转结果.我认为值得将它带入邮件列表.
文件可以更好吗?当然.有痛苦吗?不是真的,我不会让它发生.如果文档不完整,那么测试行为或在选择结构与另一个结构之前查看源是明智的.
实际上,如果Scala团队决定稍后改变行为并认为他们可以,因为行为实际上没有记录并且没有合同,那么可能会有痛苦.
为了解决评论中解释的用例,假设您已经在地图中收集了字符串频率计数(可变或不可变):
val map = Map("A" -> 5, "B" -> 12, "C" -> 2, "D" -> 9, "E" -> 18, "B" -> 5)
Run Code Online (Sandbox Code Playgroud)
由于您只需要在结尾处排序一次,您可以将元组从地图转换为a seq然后排序:
map.toSeq.sortBy(_._2)
// Seq[(java.lang.String, Int)] = ArrayBuffer((C,2), (A,5), (B,5), (D,9), (E,18))
Run Code Online (Sandbox Code Playgroud)