@@ -21,6 +21,7 @@ import java.{lang => jl, util => ju}
2121import scala .jdk .CollectionConverters ._
2222import scala .util .Try
2323import scala .util .chaining ._
24+ import scala .util .control .ControlThrowable
2425
2526/** Wrappers for exposing Scala collections as Java collections and vice-versa */
2627@ SerialVersionUID (3L )
@@ -332,7 +333,12 @@ private[collection] object JavaCollectionWrappers extends Serializable {
332333 else
333334 None
334335 }
335- override def getOrElseUpdate (key : K , op : => V ): V = underlying.computeIfAbsent(key, _ => op)
336+
337+ override def getOrElseUpdate (key : K , op : => V ): V =
338+ underlying.computeIfAbsent(key, _ => op) match {
339+ case null => update(key, null .asInstanceOf [V ]); null .asInstanceOf [V ]
340+ case v => v
341+ }
336342
337343 def addOne (kv : (K , V )): this .type = { underlying.put(kv._1, kv._2); this }
338344 def subtractOne (key : K ): this .type = { underlying remove key; this }
@@ -355,8 +361,17 @@ private[collection] object JavaCollectionWrappers extends Serializable {
355361
356362 override def update (k : K , v : V ): Unit = underlying.put(k, v)
357363
358- override def updateWith (key : K )(remappingFunction : Option [V ] => Option [V ]): Option [V ] = Option {
359- underlying.compute(key, (_, v) => remappingFunction(Option (v)).getOrElse(null .asInstanceOf [V ]))
364+ override def updateWith (key : K )(remappingFunction : Option [V ] => Option [V ]): Option [V ] = {
365+ def remap (k : K , v : V ): V =
366+ remappingFunction(Option (v)) match {
367+ case Some (null ) => throw PutNull
368+ case Some (x) => x
369+ case None => null .asInstanceOf [V ]
370+ }
371+ try Option (underlying.compute(key, remap))
372+ catch {
373+ case PutNull => update(key, null .asInstanceOf [V ]); Some (null .asInstanceOf [V ])
374+ }
360375 }
361376
362377 // support Some(null) if currently bound to null
@@ -441,7 +456,11 @@ private[collection] object JavaCollectionWrappers extends Serializable {
441456
442457 override def get (k : K ) = Option (underlying get k)
443458
444- override def getOrElseUpdate (key : K , op : => V ): V = underlying.computeIfAbsent(key, _ => op)
459+ override def getOrElseUpdate (key : K , op : => V ): V =
460+ underlying.computeIfAbsent(key, _ => op) match {
461+ case null => super /* [concurrent.Map]*/ .getOrElseUpdate(key, op)
462+ case v => v
463+ }
445464
446465 override def isEmpty : Boolean = underlying.isEmpty
447466 override def knownSize : Int = if (underlying.isEmpty) 0 else super .knownSize
@@ -462,8 +481,17 @@ private[collection] object JavaCollectionWrappers extends Serializable {
462481 case _ => Try (last).toOption
463482 }
464483
465- override def updateWith (key : K )(remappingFunction : Option [V ] => Option [V ]): Option [V ] = Option {
466- underlying.compute(key, (_, v) => remappingFunction(Option (v)).getOrElse(null .asInstanceOf [V ]))
484+ override def updateWith (key : K )(remappingFunction : Option [V ] => Option [V ]): Option [V ] = {
485+ def remap (k : K , v : V ): V =
486+ remappingFunction(Option (v)) match {
487+ case Some (null ) => throw PutNull // see scala/scala#10129
488+ case Some (x) => x
489+ case None => null .asInstanceOf [V ]
490+ }
491+ try Option (underlying.compute(key, remap))
492+ catch {
493+ case PutNull => super /* [concurrent.Map]*/ .updateWith(key)(remappingFunction)
494+ }
467495 }
468496 }
469497
@@ -572,4 +600,7 @@ private[collection] object JavaCollectionWrappers extends Serializable {
572600
573601 override def mapFactory = mutable.HashMap
574602 }
603+
604+ /** Thrown when certain Map operations attempt to put a null value. */
605+ private val PutNull = new ControlThrowable {}
575606}
0 commit comments