scala.collection.mutable.Map$WithDefault not serializable?

496 views
Skip to first unread message

adelbertc

unread,
Apr 28, 2012, 4:53:30 AM4/28/12
to scala-user
Hello,

I am trying to write a distributed graph processing library, using an
adjacency list format for the graphs. My adjacency list is defined as:

val adjList = new mutable.HashMap[Int, Vector[Int]] withDefaultValue
Vector.empty

However, when I try to distribute this graph over the network (via
Akka remote actors), I get this error:

Error[java.io.NotSerializableException:scala.collection.mutable.Map
$WithDefault

I'm pretty sure this is not a fault of Akka's, I did a Google search
and others seem to have this problem as well but I could find no
response/solution to this.. does there exist one?

Thanks!
-adelbertc

Roland Kuhn

unread,
Apr 28, 2012, 5:40:59 AM4/28/12
to adelbertc, scala-user
It may be accidental, but I think of this error as a feature: it is a bad idea to send mutable data structures between actors. Please prefer immutable.Map.

Regards,

Roland

adelbertc

unread,
Apr 28, 2012, 6:00:52 AM4/28/12
to scala-user
Ah. Well I'm never actually using the mutable.HashMap - I'm using it
in my primary constructor when I read in an edge list, I accumulate
the adjacency list in a mutable.HashMap, then finally call .toMap on
it and assign the immutable version to the actual adjacency list I use
in the other methods...

-adelbertc

On Apr 28, 2:40 am, Roland Kuhn <goo...@rkuhn.info> wrote:

Simon Ochsenreither

unread,
Apr 28, 2012, 8:20:21 AM4/28/12
to scala...@googlegroups.com

Simon Ochsenreither

unread,
Apr 28, 2012, 7:13:40 PM4/28/12
to scala...@googlegroups.com
I have looked a few minutes into it and I haven't found a reason why it shouldn't be serializable. There is nothing in the class which would completely prohibit serialization.

Kevin Wright

unread,
Apr 28, 2012, 7:31:48 PM4/28/12
to adelbertc, scala-user
toMap will return a scala.collection.Map, which is the common supertype of both collection.mutable.Map and collection.immutable.Map.

In effect, it's a null operation.  You still have the exact same HashMap, just cast to an interface that doesn't expose any mutator methods.  The concrete type is still very much mutable, and you can run into issues if you act as though it were immutable but it does, in fact, get changed elsewhere.

If you truly want to take an immutable copy, then be explicit about your intent:

  val riskyMap = HashMap(...)
  val falseSenseOfSecurity = riskyMap.toMap
  val safeCopy = Map(riskyMap: _*)

Alternatively, build directly into the immutable map in the first place.  Though this may come at a performance penalty depending on exactly how it's done.

In 2.10 we'll also be getting a rather nice concurrent map that combines mutability with snapshotting.  The snapshot then continues to be independently mutable.  Could be a perfect fit for your use-case :)

--
Kevin Wright
mail: kevin....@scalatechnology.com
gtalk / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright
steam: kev_lee_wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

Reply all
Reply to author
Forward
0 new messages