@@ -19,7 +19,8 @@ package org.apache.spark.api.java
1919
2020import com .google .common .base .Optional
2121
22- import scala .collection .convert .Wrappers .MapWrapper
22+ import java .{util => ju }
23+ import scala .collection .mutable
2324
2425private [spark] object JavaUtils {
2526 def optionToOptional [T ](option : Option [T ]): Optional [T ] =
@@ -32,7 +33,64 @@ private[spark] object JavaUtils {
3233 def mapAsSerializableJavaMap [A , B ](underlying : collection.Map [A , B ]) =
3334 new SerializableMapWrapper (underlying)
3435
36+ // Implementation is copied from scala.collection.convert.Wrappers.MapWrapper,
37+ // but implements java.io.Serializable. It can't just be subclassed to make it
38+ // Serializable since the MapWrapper class has no no-arg constructor. This class
39+ // doesn't need a no-arg constructor though.
3540 class SerializableMapWrapper [A , B ](underlying : collection.Map [A , B ])
36- extends MapWrapper (underlying) with java.io.Serializable
41+ extends ju. AbstractMap [ A , B ] with java.io.Serializable { self =>
3742
43+ override def size = underlying.size
44+
45+ override def get (key : AnyRef ): B = try {
46+ underlying get key.asInstanceOf [A ] match {
47+ case None => null .asInstanceOf [B ]
48+ case Some (v) => v
49+ }
50+ } catch {
51+ case ex : ClassCastException => null .asInstanceOf [B ]
52+ }
53+
54+ override def entrySet : ju.Set [ju.Map .Entry [A , B ]] = new ju.AbstractSet [ju.Map .Entry [A , B ]] {
55+ def size = self.size
56+
57+ def iterator = new ju.Iterator [ju.Map .Entry [A , B ]] {
58+ val ui = underlying.iterator
59+ var prev : Option [A ] = None
60+
61+ def hasNext = ui.hasNext
62+
63+ def next () = {
64+ val (k, v) = ui.next
65+ prev = Some (k)
66+ new ju.Map .Entry [A , B ] {
67+ import scala .util .hashing .byteswap32
68+ def getKey = k
69+ def getValue = v
70+ def setValue (v1 : B ) = self.put(k, v1)
71+ override def hashCode = byteswap32(k.hashCode) + (byteswap32(v.hashCode) << 16 )
72+ override def equals (other : Any ) = other match {
73+ case e : ju.Map .Entry [_, _] => k == e.getKey && v == e.getValue
74+ case _ => false
75+ }
76+ }
77+ }
78+
79+ def remove () {
80+ prev match {
81+ case Some (k) =>
82+ underlying match {
83+ case mm : mutable.Map [a, _] =>
84+ mm remove k
85+ prev = None
86+ case _ =>
87+ throw new UnsupportedOperationException (" remove" )
88+ }
89+ case _ =>
90+ throw new IllegalStateException (" next must be called at least once before remove" )
91+ }
92+ }
93+ }
94+ }
95+ }
3896}
0 commit comments