我对Scala是否提供了使用异构集合的便捷方式感兴趣?
特别是变体类型和多键 - 多重映射。
我知道第一个可以构建在嵌套的Either类Either[Either[A, B], C]
之上,第二个可以构建在嵌套的Map类Map[A, Map[B, Set[C]]]
之上,但是执行更新似乎太复杂了/每次我需要时直接删除操作(我经常需要它们)。
所以我正在寻找一个随时可用的解决方案。或者标准库中有一种方便简单的方法吗?无论如何,如果你可以建议第三方框架,也可以。
答案 0 :(得分:2)
Scala不提供便于管理异构集合的工具。
您应该使用shapeless'Either
s,而不是使用HList
的复杂嵌套,选择可能无意义的特定树结构。我不确定你会认为这很容易,但它确实比Either
- 树更紧凑(一旦你学会了足够的无形魔法)。
我熟悉的任何常用库都不支持多键映射。这样的地图有很多可能的选择:密钥是分层的还是冗余的?对称查找是否重要(例如,如果您有B => C
密钥,则可以获得映射A
;如果您有A => C
密钥,则可以获得B
?我只会注意到编写一个包装器并不难,你可以在你喜欢的任何形式的多键映射上定义自己的方法。您可能必须编写自己的包装器以获得所需的行为。最简单的只是提供2-ary包含并获取和更新方法:
implicit class NestedMapAs2Map[A, B, C](val m: Map[A, Map[B, C]]) extends AnyVal {
def contains2(a: A, b: B): Boolean = m.get(a).exists(_ contains b)
def get2(a: A, b: B): Option[C] = m.get(a).flatMap(_.get(b))
def updated2(a: A, b: B, c: C) = m.updated(a, m.get(a).map(mi => mi.updated(b,c)).getOrElse(Map(b -> c)))
}
答案 1 :(得分:1)
要创建“变体类型”,您只需使用继承。为了“保证”只存在N个变体(好吧,无论如何,从Scala代码中,不能阻止Java代码创建更多的子类),您可以使用sealed trait
。如果您需要使用已存在且无法修改(和/或移动)到您的特征extend
类型的类型,您可以将其包含在case class
中,并包含单个字段。
我认为您应该能够使用值类(如果extends AnyVal with MyTrait
是通用特征,则使用MyTrait
)来防止此上下文中的运行时开销,但我没有'试了一下。
对于multikey-multimaps,您可以使用Map[(A,B), Set[C]]
。 Scala中的元组可以从2个值到22个值。或者,还有一个MultiMap
特征,您可以将其混合到一个可变的地图中。