在Scala中我希望能够写
val petMap = ImmutableMultiMap(Alice->Cat, Bob->Dog, Alice->Hamster)
底层Map [Owner,Set [Pet]]应该同时具有Map和Set不可变。这是ImmutibleMultiMap与伴随对象的初稿:
import collection.{mutable,immutable}
class ImmutableMultiMap[K,V] extends immutable.HashMap[K,immutable.Set[V]]
object ImmutableMultiMap {
def apply[K,V](pairs: Tuple2[K,V]*): ImmutableMultiMap[K,V] = {
var m = new mutable.HashMap[K,mutable.Set[V]] with mutable.MultiMap[K,V]
for ((k,v) <- pairs) m.addBinding(k,v)
// How do I return the ImmutableMultiMap[K,V] corresponding to m here?
}
}
你能优雅地解决评论线吗?地图和集合都应该是不可变的。
谢谢!
答案 0 :(得分:5)
我已经连续两次重写同样的方法了。 :)有人真的应该让它更通用。拥有完整版本也很方便。
/**
* Like {@link scala.collection.Traversable#groupBy} but lets you return both the key and the value for the resulting
* Map-of-Lists, rather than just the key.
*
* @param in the input list
* @param f the function that maps elements in the input list to a tuple for the output map.
* @tparam A the type of elements in the source list
* @tparam B the type of the first element of the tuple returned by the function; will be used as keys for the result
* @tparam C the type of the second element of the tuple returned by the function; will be used as values for the result
* @return a Map-of-Lists
*/
def groupBy2[A,B,C](in: List[A])(f: PartialFunction[A,(B,C)]): Map[B,List[C]] = {
def _groupBy2[A, B, C](in: List[A],
got: Map[B, List[C]],
f: PartialFunction[A, (B, C)]): Map[B, List[C]] =
in match {
case Nil =>
got.map {case (k, vs) => (k, vs.reverse)}
case x :: xs if f.isDefinedAt(x) =>
val (b, c) = f(x)
val appendTo = got.getOrElse(b, Nil)
_groupBy2(xs, got.updated(b, c :: appendTo), f)
case x :: xs =>
_groupBy2(xs, got, f)
}
_groupBy2(in, Map.empty, f)
}
你这样使用它:
val xs = (1 to 10).toList
groupBy2(xs) {
case i => (i%2 == 0, i.toDouble)
}
res3: Map[Boolean,List[Double]] = Map(false -> List(1.0, 3.0, 5.0, 7.0, 9.0),
true -> List(2.0, 4.0, 6.0, 8.0, 10.0))
答案 1 :(得分:3)
你有一个更大的问题,因为ImmutableMultiMap
中没有方法会返回ImmutableMultiMap
- 因此无法向其添加元素,构造函数也不提供支持用元素创建它。请参阅现有实现,并注意随播对象的builder
及相关方法。