Scala Map和ConcurrentHashMap抛出java.lang.UnsupportedOperationException

时间:2016-07-25 13:05:32

标签: java multithreading scala containers java.util.concurrent

使用这个简单的代码

import scala.collection.JavaConversions._
new java.util.concurrent.ConcurrentHashMap[String,String]  ().toMap.put("abc","def")

Scala抛出java.lang.UnsupportedOperationException。

为什么?

2 个答案:

答案 0 :(得分:7)

这就是发生的事情(我认为):

  1. 使用new java.util.concurrent.ConcurrentHashMap[String,String]()
  2. 创建并发Java哈希映射
  3. 然后使用toMap
  4. 将其转换为不可变的scala地图
  5. 由于toMap未定义java.util.concurrent.ConcurrentHashMap,因此会应用隐式转换为可变 scala地图。 toMap然后{em> mutable Map immutable Map
  6. 然后你打电话给'把(...)'未在scala.collection.immutable.Map上定义。
  7. 然而,scala编译器方便地在导入scala.collection.immutable.Map中找到从java.util.Mapimport scala.collection.JavaConversions._的转换,其中定义了put(...)方法。但是,转换会返回一个展开AbstractMap
  8. 的包装器
  9. 但是在该包装器中没有实现put(...)方法。因此,调用最终会出现在java.util.AbstractMap的默认实现中,该实现并未真正实现put(...),而是抛出UnsupportedOperationException
  10. 我想这引起的混乱,是大多数scala开发人员现在更喜欢import scala.collection.JavaConverters._而不是import scala.collection.JavaConversions._的原因之一。

    所以,我想,这可能就是你想要做的事情:

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

答案 1 :(得分:4)

与Java不同,Scala中的默认集合是不可变的。如果您查看Map的api(找到here),您会发现Map缺少方法put。因此,例外情况告诉您,Map无法完成您希望它执行的操作。如果您想使用值填充Map

Map("abc" -> "def")

顺便说一下,不可变集合已经是线程安全的。无需使用ConcurrentHashMap