Scala增强了集合

时间:2014-01-04 21:01:56

标签: scala collections

我对Scala是否提供了使用异构集合的便捷方式感兴趣?

特别是变体类型和多键 - 多重映射。

我知道第一个可以构建在嵌套的Either类Either[Either[A, B], C]之上,第二个可以构建在嵌套的Map类Map[A, Map[B, Set[C]]]之上,但是执行更新似乎太复杂了/每次我需要时直接删除操作(我经常需要它们)。

所以我正在寻找一个随时可用的解决方案。或者标准库中有一种方便简单的方法吗?无论如何,如果你可以建议第三方框架,也可以。

2 个答案:

答案 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特征,您可以将其混合到一个可变的地图中。