Skip to content

Commit cc02de6

Browse files
mkeskellsdwijnand
authored andcommitted
less allocation on deserialisation of RedBlackTree (SortedMap)
reuse deserialisation logic for map and set
1 parent 15c847d commit cc02de6

File tree

3 files changed

+46
-34
lines changed

3 files changed

+46
-34
lines changed

library/src/scala/collection/immutable/RedBlackTree.scala

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -955,34 +955,20 @@ private[collection] object NewRedBlackTree {
955955
override def nextResult(tree: Tree[A, B]) = tree.value
956956
}
957957

958-
/** Build a Tree suitable for a TreeSet from an ordered sequence of keys */
959-
def fromOrderedKeys[A](xs: Iterator[A], size: Int): Tree[A, Null] = {
960-
val maxUsedDepth = 32 - Integer.numberOfLeadingZeros(size) // maximum depth of non-leaf nodes
961-
def f(level: Int, size: Int): Tree[A, Null] = size match {
962-
case 0 => null
963-
case 1 => mkTree(level != maxUsedDepth || level == 1, xs.next(), null, null, null)
964-
case n =>
965-
val leftSize = (size-1)/2
966-
val left = f(level+1, leftSize)
967-
val x = xs.next()
968-
val right = f(level+1, size-1-leftSize)
969-
BlackTree(x, null, left, right)
970-
}
971-
f(1, size)
972-
}
973-
974-
/** Build a Tree suitable for a TreeMap from an ordered sequence of key/value pairs */
975-
def fromOrderedEntries[A, B](xs: Iterator[(A, B)], size: Int): Tree[A, B] = {
958+
/** Build a Tree from an ordered sequence of key and values */
959+
def fromOrderedEntries[A, B](keys: Iterator[A], values: Iterator[B], size: Int): Tree[A, B] = {
976960
val maxUsedDepth = 32 - Integer.numberOfLeadingZeros(size) // maximum depth of non-leaf nodes
977961
def f(level: Int, size: Int): Tree[A, B] = size match {
978962
case 0 => null
979963
case 1 =>
980-
val (k, v) = xs.next()
964+
val k = keys.next()
965+
val v = values.next()
981966
mkTree(level != maxUsedDepth || level == 1, k, v, null, null)
982967
case n =>
983968
val leftSize = (size-1)/2
984969
val left = f(level+1, leftSize)
985-
val (k, v) = xs.next()
970+
val k = keys.next()
971+
val v = values.next()
986972
val right = f(level+1, size-1-leftSize)
987973
BlackTree(k, v, left, right)
988974
}

library/src/scala/collection/immutable/TreeMap.scala

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,26 @@ object TreeMap extends ImmutableSortedMapFactory[TreeMap] {
106106
private[this] def readObject(in: java.io.ObjectInputStream) = {
107107
val size = in.readInt()
108108
ordering = in.readObject().asInstanceOf[Ordering[A]]
109-
implicit val ord = ordering
110-
111-
val data = Array.newBuilder[(A, B)]
112-
data.sizeHint(size)
113-
for (i <- 0 until size) {
114-
val key = in.readObject().asInstanceOf[A]
115-
val value = in.readObject().asInstanceOf[B]
116-
data += ((key, value))
109+
size match {
110+
case 0 => //tree is null already
111+
case 1 =>
112+
val key = in.readObject().asInstanceOf[A]
113+
val value = in.readObject().asInstanceOf[B]
114+
tree = RB.update(null, key, value, true)(ordering)
115+
case _ =>
116+
val keys = new Array[Any](size)
117+
val values = new Array[Any](size)
118+
var i = 0
119+
while (i < size) {
120+
keys(i) = in.readObject()
121+
values(i) = in.readObject()
122+
i += 1
123+
}
124+
tree = RB.fromOrderedEntries(
125+
keys.iterator.asInstanceOf[Iterator[A]],
126+
values.iterator.asInstanceOf[Iterator[B]],
127+
size)
117128
}
118-
tree = RB.fromOrderedEntries(data.result.iterator, size)
119129
}
120130
@throws[IOException]
121131
private[this] def readResolve(): AnyRef =

library/src/scala/collection/immutable/TreeSet.scala

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,32 @@ object TreeSet extends ImmutableSortedSetFactory[TreeSet] {
8585
private[this] def readObject(in: java.io.ObjectInputStream) = {
8686
val size = in.readInt()
8787
ordering = in.readObject().asInstanceOf[Ordering[A]]
88-
val data = Iterable.newBuilder[A]
89-
data.sizeHint(size)
90-
for (i <- 0 until size)
91-
data += in.readObject().asInstanceOf[A]
92-
tree = RB.fromOrderedKeys(data.result.iterator, size)
88+
size match {
89+
case 0 => //tree is null already
90+
case 1 =>
91+
val entry = in.readObject().asInstanceOf[A]
92+
tree = RB.update(null, entry, (), false)(ordering)
93+
case _ =>
94+
val entries = new Array[Any](size)
95+
var i = 0
96+
while (i < size) {
97+
entries(i) = in.readObject()
98+
i += 1
99+
}
100+
tree = RB.fromOrderedEntries(
101+
entries.iterator.asInstanceOf[Iterator[A]],
102+
unitsIterator,
103+
size)
104+
}
93105
}
94106
@throws[IOException]
95107
private[this] def readResolve(): AnyRef =
96108
new TreeSet(tree)(ordering)
97109
}
110+
private[this] object unitsIterator extends AbstractIterator[Unit] {
111+
override def hasNext: Boolean = true
112+
override def next(): Unit = ()
113+
}
98114
}
99115

100116
/** This class implements immutable sets using a tree.

0 commit comments

Comments
 (0)