Skip to content

Commit d526e10

Browse files
committed
Add immutable SeqMap to stdlib
1 parent c16afe5 commit d526e10

File tree

1 file changed

+278
-0
lines changed

1 file changed

+278
-0
lines changed
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala
14+
package collection
15+
package immutable
16+
17+
import scala.collection.mutable.{Builder, ReusableBuilder}
18+
import language.experimental.captureChecking
19+
import scala.annotation.unchecked.uncheckedCaptures
20+
21+
/** A base trait for ordered, immutable maps.
22+
*
23+
* Note that the [[equals]] method for [[SeqMap]] compares key-value pairs
24+
* without regard to ordering.
25+
*
26+
* All behavior is defined in terms of the abstract methods in `SeqMap`.
27+
* It is sufficient for concrete subclasses to implement those methods.
28+
* Methods that return a new map, in particular [[removed]] and [[updated]], must preserve ordering.
29+
*
30+
* @tparam K the type of the keys contained in this linked map.
31+
* @tparam V the type of the values associated with the keys in this linked map.
32+
*
33+
* @define coll immutable seq map
34+
* @define Coll `immutable.SeqMap`
35+
*/
36+
37+
trait SeqMap[K, +V]
38+
extends Map[K, V]
39+
with collection.SeqMap[K, V]
40+
with MapOps[K, V, SeqMap, SeqMap[K, V]]
41+
with MapFactoryDefaults[K, V, SeqMap, Iterable] {
42+
override def mapFactory: MapFactory[SeqMap] = SeqMap
43+
}
44+
45+
46+
object SeqMap extends MapFactory[SeqMap] {
47+
def empty[K, V]: SeqMap[K, V] = EmptySeqMap.asInstanceOf[SeqMap[K, V]]
48+
49+
def from[K, V](it: collection.IterableOnce[(K, V)]^): SeqMap[K, V] =
50+
it match {
51+
case sm: SeqMap[K, V] => sm
52+
case _ => (newBuilder[K, V] ++= it).result()
53+
}
54+
55+
def newBuilder[K, V]: Builder[(K, V), SeqMap[K, V]] = new SeqMapBuilderImpl
56+
57+
@SerialVersionUID(3L)
58+
private object EmptySeqMap extends SeqMap[Any, Nothing] with Serializable {
59+
override def size: Int = 0
60+
override def knownSize: Int = 0
61+
override def apply(key: Any) = throw new NoSuchElementException("key not found: " + key)
62+
override def contains(key: Any) = false
63+
def get(key: Any): Option[Nothing] = None
64+
override def getOrElse [V1](key: Any, default: => V1): V1 = default
65+
def iterator: Iterator[(Any, Nothing)] = Iterator.empty
66+
def updated [V1] (key: Any, value: V1): SeqMap[Any, V1] = new SeqMap1(key, value)
67+
def removed(key: Any): SeqMap[Any, Nothing] = this
68+
}
69+
70+
@SerialVersionUID(3L)
71+
private final class SeqMap1[K, +V](key1: K, value1: V) extends SeqMap[K,V] with Serializable {
72+
override def size: Int = 1
73+
override def knownSize: Int = 1
74+
override def apply(key: K) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key)
75+
override def contains(key: K) = key == key1
76+
def get(key: K): Option[V] =
77+
if (key == key1) Some(value1) else None
78+
override def getOrElse [V1 >: V](key: K, default: => V1): V1 =
79+
if (key == key1) value1 else default
80+
def iterator = Iterator.single((key1, value1))
81+
def updated[V1 >: V](key: K, value: V1): SeqMap[K, V1] =
82+
if (key == key1) new SeqMap1(key1, value)
83+
else new SeqMap2(key1, value1, key, value)
84+
def removed(key: K): SeqMap[K, V] =
85+
if (key == key1) SeqMap.empty else this
86+
override def foreach[U](f: ((K, V)) => U): Unit = {
87+
f((key1, value1))
88+
}
89+
override def foreachEntry[U](f: (K, V) => U): Unit = {
90+
f(key1, value1)
91+
}
92+
}
93+
94+
@SerialVersionUID(3L)
95+
private final class SeqMap2[K, +V](key1: K, value1: V, key2: K, value2: V) extends SeqMap[K,V] with Serializable {
96+
override def size: Int = 2
97+
override def knownSize: Int = 2
98+
override def apply(key: K) =
99+
if (key == key1) value1
100+
else if (key == key2) value2
101+
else throw new NoSuchElementException("key not found: " + key)
102+
override def contains(key: K) = (key == key1) || (key == key2)
103+
def get(key: K): Option[V] =
104+
if (key == key1) Some(value1)
105+
else if (key == key2) Some(value2)
106+
else None
107+
override def getOrElse [V1 >: V](key: K, default: => V1): V1 =
108+
if (key == key1) value1
109+
else if (key == key2) value2
110+
else default
111+
def iterator = ((key1, value1) :: (key2, value2) :: Nil).iterator
112+
def updated[V1 >: V](key: K, value: V1): SeqMap[K, V1] =
113+
if (key == key1) new SeqMap2(key1, value, key2, value2)
114+
else if (key == key2) new SeqMap2(key1, value1, key2, value)
115+
else new SeqMap3(key1, value1, key2, value2, key, value)
116+
def removed(key: K): SeqMap[K, V] =
117+
if (key == key1) new SeqMap1(key2, value2)
118+
else if (key == key2) new SeqMap1(key1, value1)
119+
else this
120+
override def foreach[U](f: ((K, V)) => U): Unit = {
121+
f((key1, value1)); f((key2, value2))
122+
}
123+
override def foreachEntry[U](f: (K, V) => U): Unit = {
124+
f(key1, value1)
125+
f(key2, value2)
126+
}
127+
}
128+
129+
@SerialVersionUID(3L)
130+
private class SeqMap3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends SeqMap[K,V] with Serializable {
131+
override def size: Int = 3
132+
override def knownSize: Int = 3
133+
override def apply(key: K) =
134+
if (key == key1) value1
135+
else if (key == key2) value2
136+
else if (key == key3) value3
137+
else throw new NoSuchElementException("key not found: " + key)
138+
override def contains(key: K) = (key == key1) || (key == key2) || (key == key3)
139+
def get(key: K): Option[V] =
140+
if (key == key1) Some(value1)
141+
else if (key == key2) Some(value2)
142+
else if (key == key3) Some(value3)
143+
else None
144+
override def getOrElse [V1 >: V](key: K, default: => V1): V1 =
145+
if (key == key1) value1
146+
else if (key == key2) value2
147+
else if (key == key3) value3
148+
else default
149+
def iterator = ((key1, value1) :: (key2, value2) :: (key3, value3) :: Nil).iterator
150+
def updated[V1 >: V](key: K, value: V1): SeqMap[K, V1] =
151+
if (key == key1) new SeqMap3(key1, value, key2, value2, key3, value3)
152+
else if (key == key2) new SeqMap3(key1, value1, key2, value, key3, value3)
153+
else if (key == key3) new SeqMap3(key1, value1, key2, value2, key3, value)
154+
else new SeqMap4(key1, value1, key2, value2, key3, value3, key, value)
155+
def removed(key: K): SeqMap[K, V] =
156+
if (key == key1) new SeqMap2(key2, value2, key3, value3)
157+
else if (key == key2) new SeqMap2(key1, value1, key3, value3)
158+
else if (key == key3) new SeqMap2(key1, value1, key2, value2)
159+
else this
160+
override def foreach[U](f: ((K, V)) => U): Unit = {
161+
f((key1, value1)); f((key2, value2)); f((key3, value3))
162+
}
163+
override def foreachEntry[U](f: (K, V) => U): Unit = {
164+
f(key1, value1)
165+
f(key2, value2)
166+
f(key3, value3)
167+
}
168+
}
169+
170+
@SerialVersionUID(3L)
171+
private final class SeqMap4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends SeqMap[K,V] with Serializable {
172+
override def size: Int = 4
173+
override def knownSize: Int = 4
174+
override def apply(key: K) =
175+
if (key == key1) value1
176+
else if (key == key2) value2
177+
else if (key == key3) value3
178+
else if (key == key4) value4
179+
else throw new NoSuchElementException("key not found: " + key)
180+
override def contains(key: K) = (key == key1) || (key == key2) || (key == key3) || (key == key4)
181+
def get(key: K): Option[V] =
182+
if (key == key1) Some(value1)
183+
else if (key == key2) Some(value2)
184+
else if (key == key3) Some(value3)
185+
else if (key == key4) Some(value4)
186+
else None
187+
override def getOrElse [V1 >: V](key: K, default: => V1): V1 =
188+
if (key == key1) value1
189+
else if (key == key2) value2
190+
else if (key == key3) value3
191+
else if (key == key4) value4
192+
else default
193+
def iterator = ((key1, value1) :: (key2, value2) :: (key3, value3) :: (key4, value4) :: Nil).iterator
194+
def updated[V1 >: V](key: K, value: V1): SeqMap[K, V1] =
195+
if (key == key1) new SeqMap4(key1, value, key2, value2, key3, value3, key4, value4)
196+
else if (key == key2) new SeqMap4(key1, value1, key2, value, key3, value3, key4, value4)
197+
else if (key == key3) new SeqMap4(key1, value1, key2, value2, key3, value, key4, value4)
198+
else if (key == key4) new SeqMap4(key1, value1, key2, value2, key3, value3, key4, value)
199+
else {
200+
// Directly create the elements for performance reasons
201+
val fields = Vector(key1, key2, key3, key4, key)
202+
val underlying: Map[K, (Int, V1)] =
203+
HashMap(
204+
(key1, (0, value1)),
205+
(key2, (1, value2)),
206+
(key3, (2, value3)),
207+
(key4, (3, value4)),
208+
(key, (4, value))
209+
)
210+
new VectorMap(fields, underlying)
211+
}
212+
def removed(key: K): SeqMap[K, V] =
213+
if (key == key1) new SeqMap3(key2, value2, key3, value3, key4, value4)
214+
else if (key == key2) new SeqMap3(key1, value1, key3, value3, key4, value4)
215+
else if (key == key3) new SeqMap3(key1, value1, key2, value2, key4, value4)
216+
else if (key == key4) new SeqMap3(key1, value1, key2, value2, key3, value3)
217+
else this
218+
override def foreach[U](f: ((K, V)) => U): Unit = {
219+
f((key1, value1)); f((key2, value2)); f((key3, value3)); f((key4, value4))
220+
}
221+
override def foreachEntry[U](f: (K, V) => U): Unit = {
222+
f(key1, value1)
223+
f(key2, value2)
224+
f(key3, value3)
225+
f(key4, value4)
226+
}
227+
228+
private[SeqMap] def buildTo[V1 >: V](builder: Builder[(K, V1), SeqMap[K, V1]]): builder.type =
229+
builder.addOne((key1, value1)).addOne((key2, value2)).addOne((key3, value3)).addOne((key4, value4))
230+
}
231+
232+
private final class SeqMapBuilderImpl[K, V] extends ReusableBuilder[(K, V), SeqMap[K, V]] {
233+
private[this] var elems: SeqMap[K, V] @uncheckedCaptures = SeqMap.empty
234+
private[this] var switchedToVectorMapBuilder: Boolean = false
235+
private[this] var vectorMapBuilder: VectorMapBuilder[K, V] @uncheckedCaptures = _
236+
237+
override def clear(): Unit = {
238+
elems = SeqMap.empty
239+
if (vectorMapBuilder != null) {
240+
vectorMapBuilder.clear()
241+
}
242+
switchedToVectorMapBuilder = false
243+
}
244+
245+
override def result(): SeqMap[K, V] =
246+
if (switchedToVectorMapBuilder) vectorMapBuilder.result() else elems
247+
248+
def addOne(elem: (K, V)) = {
249+
if (switchedToVectorMapBuilder) {
250+
vectorMapBuilder.addOne(elem)
251+
} else if (elems.size < 4) {
252+
elems = elems + elem
253+
} else {
254+
// assert(elems.size == 4)
255+
if (elems.contains(elem._1)) {
256+
elems = elems + elem // will not increase the size of the map
257+
} else {
258+
switchedToVectorMapBuilder = true
259+
if (vectorMapBuilder == null) {
260+
vectorMapBuilder = new VectorMapBuilder
261+
}
262+
elems.asInstanceOf[SeqMap4[K, V]].buildTo(vectorMapBuilder)
263+
vectorMapBuilder.addOne(elem)
264+
}
265+
}
266+
267+
this
268+
}
269+
270+
override def addAll(xs: IterableOnce[(K, V)]^): this.type =
271+
if (switchedToVectorMapBuilder) {
272+
vectorMapBuilder.addAll(xs)
273+
this
274+
} else {
275+
super.addAll(xs)
276+
}
277+
}
278+
}

0 commit comments

Comments
 (0)