11package scala .collection
22
3+ import annotation .unchecked .uncheckedVariance
4+ import scala .util .hashing .MurmurHash3
5+
36/**
47 * A multidict is a map that can associate a set of values to a given key.
58 *
@@ -14,7 +17,7 @@ trait MultiDict[K, V]
1417 def multiMapFactory : MapFactory [MultiDictCC ] = MultiDict
1518
1619 override protected [this ] def fromSpecificIterable (coll : Iterable [(K , V )]): MultiDictCC [K , V ] = multiMapFactory.from(coll)
17- override protected [this ] def newSpecificBuilder () : mutable.Builder [(K , V ), MultiDictCC [K , V ]] = multiMapFactory.newBuilder[K , V ]()
20+ override protected [this ] def newSpecificBuilder : mutable.Builder [(K , V ), MultiDictCC [K , V ]] = multiMapFactory.newBuilder[K , V ]
1821
1922 def canEqual (that : Any ): Boolean = true
2023
@@ -32,15 +35,15 @@ trait MultiDict[K, V]
3235 case _ => false
3336 }
3437
35- override def hashCode (): Int = Set .unorderedHash(sets, " MultiMap" .## )
38+ override def hashCode (): Int = MurmurHash3 .unorderedHash(sets, " MultiMap" .## )
3639
3740}
3841
3942
4043trait MultiDictOps [K , V , + CC [X , Y ] <: MultiDict [X , Y ], + C <: MultiDict [K , V ]]
4144 extends IterableOps [(K , V ), Iterable , C ] {
4245
43- protected [this ] type MultiDictCC [K , V ] = CC [K , V ]
46+ protected [this ] type MultiDictCC [K , V ] = CC [K , V ] @ uncheckedVariance
4447
4548 def multiMapFactory : MapFactory [MultiDictCC ]
4649
@@ -58,8 +61,8 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
5861 */
5962 def sets : Map [K , Set [V ]]
6063
61- def iterator () : Iterator [(K , V )] =
62- sets.iterator() .flatMap { case (k, vs) => vs.view.map(v => (k, v)) }
64+ def iterator : Iterator [(K , V )] =
65+ sets.iterator.flatMap { case (k, vs) => vs.view.map(v => (k, v)) }
6366
6467 /**
6568 * @return The set of values associated with the given `key`, or the empty
@@ -133,13 +136,8 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
133136 def concat (that : Iterable [(K , V )]): C =
134137 fromSpecificIterable(new View .Concat (toIterable, that))
135138
136- override def withFilter (p : ((K , V )) => Boolean ): MultiMapWithFilter = new MultiMapWithFilter (p)
137-
138- class MultiMapWithFilter (p : ((K , V )) => Boolean ) extends WithFilter (p) {
139- def map [L , W ](f : ((K , V )) => (L , W )): CC [L , W ] = multiMapFromIterable(new View .Map (filtered, f))
140- def flatMap [L , W ](f : ((K , V )) => IterableOnce [(L , W )]): CC [L , W ] = multiMapFromIterable(new View .FlatMap (filtered, f))
141- override def withFilter (q : ((K , V )) => Boolean ): MultiMapWithFilter = new MultiMapWithFilter (kv => p(kv) && q(kv))
142- }
139+ override def withFilter (p : ((K , V )) => Boolean ): MultiDictOps .WithFilter [K , V , IterableCC , CC ] =
140+ new MultiDictOps .WithFilter (this , p)
143141
144142 /**
145143 * @return Whether there exists a value associated with the given `key`
@@ -203,4 +201,23 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]]
203201
204202}
205203
206- object MultiDict extends MapFactory .Delegate [MultiDict ](immutable.MultiDict )
204+ object MultiDictOps {
205+
206+ class WithFilter [K , V , + IterableCC [_], + CC [X , Y ] <: MultiDict [X , Y ]](
207+ `this` : MultiDictOps [K , V , CC , _] with IterableOps [(K , V ), IterableCC , _],
208+ p : ((K , V )) => Boolean
209+ ) extends IterableOps .WithFilter [(K , V ), IterableCC ](`this`, p) {
210+
211+ def map [L , W ](f : ((K , V )) => (L , W )): CC [L , W ] =
212+ `this`.multiMapFactory.from(new View .Map (filtered, f))
213+
214+ def flatMap [L , W ](f : ((K , V )) => IterableOnce [(L , W )]): CC [L , W ] =
215+ `this`.multiMapFactory.from(new View .FlatMap (filtered, f))
216+
217+ override def withFilter (q : ((K , V )) => Boolean ): WithFilter [K , V , IterableCC , CC ] =
218+ new WithFilter [K , V , IterableCC , CC ](`this`, (kv : (K , V )) => p(kv) && q(kv))
219+ }
220+
221+ }
222+
223+ object MultiDict extends MapFactory .Delegate [MultiDict ](immutable.MultiDict )
0 commit comments