Search code examples
scalaconcurrenthashmap

How to use ConcurrentHashMap computeIfAbsent() in Scala


I'm using a ConcurrentHashMap in Scala and I would like to use the computeIfAbsent() method but can't figure out the syntax for the second argument. Can someone show me what would be the proper syntax?

When running the following code

val data = new ConcurrentHashMap[String, LongAdder]

data.computeIfAbsent("bob", k: String => new LongAdder()).increment()

I'm getting the following error

Type mismatch, expected: Function[_ >: String, _ <: LongAdder], actual: (String) => Any

Thanking you in advance

Francis


Solution

  • The problem is that you're using java.util.concurrent.ConcurrentHashMap, which accepts java.util.function.Function as a parameter for computeIfAbsent() instead of scala.Function1 which you pass to it.

    Since scala doesn't support lambda conversion for functional interfaces as Java does (at least not without the -Xexperimental flag), you can solve this by implementing a java.util.function.Function explicitly:

    val data = new ConcurrentHashMap[String, LongAdder]
    val adderSupplier = new java.util.function.Function[String, LongAdder]() {
      override def apply(t: String): LongAdder = new LongAdder()
    }
    data.computeIfAbsent("bob", adderSupplier).increment()
    

    Alternatively, if you need this more often, you may write a utility conversion function or even an implicit conversion:

    object FunctionConverter {
      implicit def scalaFunctionToJava[From, To](function: (From) => To): java.util.function.Function[From, To] = {
        new java.util.function.Function[From, To] {
          override def apply(input: From): To = function(input)
        }
      }
    }
    
    import FunctionConverter._
    val data = new ConcurrentHashMap[String, LongAdder]()
    data.computeIfAbsent("bob", (k: String) => new LongAdder()) // <- implicit conversion applied here