你可以用非循环可变数据结构做的任何事情,你也可以用不可变数据结构做。诀窍很简单:
loop -> recursion or fold
mutating operation -> new-copy-with-change-made operation
因此,例如,在您的情况下,您可能Iterable
每次都在循环并添加一个值。如果我们应用我们得心应手的技巧,我们
def mkMap[K,V](data: Iterable[(K,V)]): Map[K, Iterable[V]] = {
@annotation.tailrec def mkMapInner(
data: Iterator[(K,V)],
map: Map[K,Vector[V]] = Map.empty[K,Vector[V]]
): Map[K,Vector[V]] = {
if (data.hasNext) {
val (k,v) = data.next
mkMapInner(data, map + (k -> map.get(k).map(_ :+ v).getOrElse(Vector(v))))
}
else map
}
mkMapInner(data.iterator)
}
在这里,我选择通过声明递归内部方法来实现循环替换(使用 @annotation.tailrec 检查递归是否优化为 while 循环,因此它不会破坏堆栈)
让我们测试一下:
val pairs = Iterable((1,"flounder"),(2,"salmon"),(1,"halibut"))
scala> mkMap(pairs)
res2: Map[Int,Iterable[java.lang.String]] =
Map(1 -> Vector(flounder, halibut), 2 -> Vector(salmon))
现在,事实证明 Scala 的集合库也包含一些有用的东西:
scala> pairs.groupBy(_._1).mapValues{ _.map{_._2 } }
作为groupBy
关键方法,其余的将它产生的内容清理成你想要的形式。