前几天我想知道为什么scala.collection.Map将其解压缩方法定义为
def unzip [A1, A2] (implicit asPair: ((A, B)) ⇒ (A1, A2)): (Iterable[A1], Iterable[A2])
由于该方法仅“返回”一对Iterable而不是一对Seq,因此无法保证原始映射中的键/值对出现在返回序列中的匹配索引处,因为Iterable不保证顺序遍历。所以,如果我有一个
Map((1,A), (2,B))
,然后调用
Map((1,A), (2,B)) unzip
我可能会以
结束... = (List(1, 2),List(A, B))
和
一样... = (List(2, 1),List(B, A))
虽然我可以想象这背后的存储相关原因(例如,想想HashMaps),我想知道你们对这种行为的看法。对于Map.unzip方法的用户来说,可能会看到项目以相同的顺序返回(我打赌这可能几乎总是如此)但是因为无法保证这可能反过来产生难以发现的错误图书馆用户的代码。
也许这种行为应该在附带的scaladoc中更明确地表达出来?
编辑:请注意,我并不是将地图称为有序集合。我只对解压缩后的“匹配”序列感兴趣,即
val (keys, values) = someMap.unzip
它适用于所有i(keys(i),values(i))是原始映射的元素。
答案 0 :(得分:3)
如果您展开unzip
的说明,您将得到答案:
definition classes: GenericTraversableTemplate
换句话说,它没有专门用于Map
。
但你的论点是合理的,如果你用你的推理打开一张增强票,我敢说你可能会得到你的意愿。特别是如果你继续生产一个补丁 - 如果没有别的,至少你会学到更多关于Scala集合的知识。
答案 1 :(得分:3)
实际上,您提供的示例不会发生。 Map
将始终以成对方式解压缩。您Iterable
不保证订购的陈述并非完全正确。更准确地说任何给定的Iterable
都不必保证排序,但这取决于实现。在Map.unzip
的情况下,不保证对的排序,但是对中的项目不会随着它们的匹配而改变 - 匹配是Map
的基本属性。您可以阅读the source至GenericTraversableTemplate
以验证是否属实。
答案 2 :(得分:2)
地图通常没有自然序列:它们是无序集合。你的钥匙碰巧有自然顺序的事实并没有改变一般情况。
(但是我无法解释为什么Map有zipWithIndex
方法。这为我的观点提供了一个反驳论点。我想它与其他集合是一致的,尽管它提供了索引,在随后的电话中,不保证它们是相同的。)
答案 3 :(得分:0)
如果使用LinkedHashMap或LinkedHashSet,迭代器应该以原始插入顺序返回对。其他HashMaps,是的,你无法控制。保留原始插入顺序在UI上下文中非常有用,它允许您在不改变类型的情况下在Web应用程序的任何列上求助表。