Skip to content

Commit be4b31b

Browse files
committed
take control of the serialised form of a TreeMap/TreeSet
use a more efficient construction of the RedBlackTree from (new) serialised form using the newer RedBlackTree APIs
1 parent a8d2c26 commit be4b31b

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ package scala
1414
package collection
1515
package immutable
1616

17+
import java.io.IOException
18+
1719
import generic._
1820
import immutable.{RedBlackTree => RB}
1921
import mutable.Builder
@@ -88,6 +90,41 @@ object TreeMap extends ImmutableSortedMapFactory[TreeMap] {
8890

8991
override def result(): TreeMap[A, B] = new TreeMap(tree)(ordering)
9092
}
93+
private val legacySerialisation = System.getProperty("scala.collection.immutable.TreeMap.newSerialisation", "false") != "false"
94+
95+
private class TreeMapProxy[A, B](
96+
@transient private[this] var tree: RedBlackTree.Tree[A, B],
97+
@transient private[this] var ordering: Ordering[A]) extends Serializable {
98+
99+
@throws[IOException]
100+
private[this] def writeObject(out: java.io.ObjectOutputStream) = {
101+
out.writeInt(RB.count(tree))
102+
out.writeObject(ordering)
103+
RB.foreachEntry(tree, {
104+
(k: A, v: B) =>
105+
out.writeObject(k)
106+
out.writeObject(v)
107+
})
108+
}
109+
@throws[IOException]
110+
private[this] def readObject(in: java.io.ObjectInputStream) = {
111+
val size = in.readInt()
112+
ordering = in.readObject().asInstanceOf[Ordering[A]]
113+
implicit val ord = ordering
114+
115+
val data = Array.newBuilder[(A, B)]
116+
data.sizeHint(size)
117+
for (i <- 0 until size) {
118+
val key = in.readObject().asInstanceOf[A]
119+
val value = in.readObject().asInstanceOf[B]
120+
data += ((key, value))
121+
}
122+
tree = RB.fromOrderedEntries(data.result.iterator, size)
123+
}
124+
@throws[IOException]
125+
private[this] def readResolve(): AnyRef =
126+
new TreeMap(tree)(ordering)
127+
}
91128
}
92129

93130
/** This class implements immutable maps using a tree.
@@ -346,4 +383,8 @@ final class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering:
346383
newMapOrSelf(RB.transform[A, B, W](tree, f)).asInstanceOf[That]
347384
else super.transform(f)
348385
}
386+
387+
@throws[IOException]
388+
private[this] def writeReplace(out: java.io.ObjectOutputStream): AnyRef =
389+
if (TreeMap.legacySerialisation) this else new TreeMap.TreeMapProxy(tree, ordering)
349390
}

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ package scala
1414
package collection
1515
package immutable
1616

17+
import java.io.IOException
18+
1719
import generic._
1820
import immutable.{RedBlackTree => RB}
1921
import mutable.Builder
@@ -54,6 +56,32 @@ object TreeSet extends ImmutableSortedSetFactory[TreeSet] {
5456

5557
override def result(): TreeSet[A] = new TreeSet(tree)(ordering)
5658
}
59+
private val legacySerialisation = System.getProperty("scala.collection.immutable.TreeSet.newSerialisation", "false") != "false"
60+
61+
private class TreeSetProxy[A](
62+
@transient private[this] var tree: RedBlackTree.Tree[A, Any],
63+
@transient private[this] var ordering: Ordering[A]) extends Serializable {
64+
65+
@throws[IOException]
66+
private[this] def writeObject(out: java.io.ObjectOutputStream) = {
67+
out.writeInt(RB.count(tree))
68+
out.writeObject(ordering)
69+
RB.foreachKey(tree, out.writeObject)
70+
}
71+
@throws[IOException]
72+
private[this] def readObject(in: java.io.ObjectInputStream) = {
73+
val size = in.readInt()
74+
ordering = in.readObject().asInstanceOf[Ordering[A]]
75+
val data = Iterable.newBuilder[A]
76+
data.sizeHint(size)
77+
for (i <- 0 until size)
78+
data += in.readObject().asInstanceOf[A]
79+
tree = RB.fromOrderedKeys(data.result.iterator, size)
80+
}
81+
@throws[IOException]
82+
private[this] def readResolve(): AnyRef =
83+
new TreeSet(tree)(ordering)
84+
}
5785
}
5886

5987
/** This class implements immutable sets using a tree.
@@ -252,4 +280,7 @@ final class TreeSet[A] private[immutable] (private[immutable] val tree: RB.Tree[
252280
case _ => super.equals(obj)
253281
}
254282

283+
@throws[IOException]
284+
private[this] def writeReplace(out: java.io.ObjectOutputStream): AnyRef =
285+
if (TreeSet.legacySerialisation) this else new TreeSet.TreeSetProxy(tree, ordering)
255286
}

0 commit comments

Comments
 (0)