微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么可变和不可变的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))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐