Scala Map and ConcurrentHashMap throw a java.lang.UnsupportedOperationException Scala Map and ConcurrentHashMap throw a java.lang.UnsupportedOperationException multithreading multithreading

Scala Map and ConcurrentHashMap throw a java.lang.UnsupportedOperationException


Well this is what happens (I think):

  1. You create a concurrent java hash map with new java.util.concurrent.ConcurrentHashMap[String,String]()
  2. Then you convert it to an immutable scala Map with toMap
  3. As toMapis not defined on java.util.concurrent.ConcurrentHashMap an implicit conversion to a mutable scala map is applied. And toMap then makes of this mutable Map an immutable Map.
  4. Then you call 'put(...)' which is not defined on scala.collection.immutable.Map.
  5. The scala compiler however, conveniently, finds a conversion from scala.collection.immutable.Map to java.util.Map in your import import scala.collection.JavaConversions._ which has a put(...) method defined. However, the conversion returns a wrapper extending AbstractMap.
  6. But there is no put(...) method implemented in that wrapper. Therefore, the call ends up in the default implementation of java.util.AbstractMap which does not really implement put(...) but instead throws an UnsupportedOperationException

I guess the confusion caused by this, is one reason most scala developers prefer import scala.collection.JavaConverters._ over import scala.collection.JavaConversions._ nowadays.

So, I think, this might be what you want to do:

import scala.collection.JavaConverters._new java.util.concurrent.ConcurrentHashMap[String,String]().asScala.put("abc","def")    


Unlike Java, the default collections in Scala are immutable. If you take a look at the api for Map (found here) you'll see that Map lacks a method put. So the exception is telling you, quite rightly, that Map can't do what you want it to do. If you want to fill the Map with values:

Map("abc" -> "def")

By the way, an immutable collection is already thread-safe. No need to use a ConcurrentHashMap.