为什么可变和不可变 ListMap 在 Scala 中有不同的顺序? [英] Why do mutable and immutable ListMaps have different orders in Scala?

查看:51
本文介绍了为什么可变和不可变 ListMap 在 Scala 中有不同的顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Why does the immutable version of the ListMap store in ascending order, while mutable version stores in descending order?

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

Here is a test that you can use if you got scalatest-1.6.1.jar and 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 测试的输出:

Heres the output of the PASSING test :

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 调用由可变或不可变列表支持的列表映射.规则是将保留插入顺序.

The "sorting" in your code is not the core of the issue, your call to ListMap is using the ListMap.apply call from the companion object that constructs a list map backed by a mutable or immutable list. The rule is that the insertion order will be preserved.

区别似乎是可变列表由一个不可变列表支持,插入发生在前面.所以这就是为什么在迭代时你会得到 LIFO 行为.我仍然在寻找不可变的,但我敢打赌插入物有效地在后面.编辑,我改变主意:插入可能在前面,但似乎 immutable.ListMap.iterator 方法决定用 toList.reverseIterator 反转结果在返回的迭代器上.我认为值得将其加入邮件列表.

The difference seems to be that mutable list is backed by an immutable list and insert happens at the front. So that's why when iterating you get LIFO behavior. I'm still looking at the immutable one but I bet the inserts are effectively at the back. Edit, I'm changing my mind: insert are probably at the front, but it seems the immutable.ListMap.iterator method decides to reverse the result with a toList.reverseIterator on the returned iterator. I think it worth bringing it in the mailing list.

文档会更好吗?当然.有痛吗?不是真的,我不会让它发生.如果文档不完整,明智的做法是在选择结构与另一个结构之前测试行为或查看源代码.

Could the documentation be better? Certainly. Is there pain? Not really, I don't let it happen. If the documentation is incomplete, it's wise to test the behavior or go look up at the source before picking a structure versus another one.

实际上,如果 Scala 团队决定在以后改变行为并认为他们可以改变,那可能会很痛苦,因为该行为实际上没有记录在案且没有合同.

Actually, there can be pain if the Scala team decides to change behavior at a later time and feel they can because the behavior is effectively undocumented and there is no contract.

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

To address your use case explained in the the comment, say you've collected the string frequency count in a map (mutable or immutable):

val map = Map("A" -> 5, "B" -> 12, "C" -> 2, "D" -> 9, "E" -> 18, "B" -> 5)

由于最后只需要排序一次,所以可以将map中的元组转换成seq然后排序:

Since you only need to sort once at the end, you can convert the tuples from the map to a seq and then sort:

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

这篇关于为什么可变和不可变 ListMap 在 Scala 中有不同的顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆