将java.util.IdentityHashMap转换为scala.immutable.Map [英] Convert java.util.IdentityHashMap to scala.immutable.Map

查看:1324
本文介绍了将java.util.IdentityHashMap转换为scala.immutable.Map的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

java.util.IdentityHashMap [A​​,B] 转换为的子类型的最简单方法是scala.immutable.Map [ A,B] ?我需要保持键分开,除非他们 eq

What is the simplest way to convert a java.util.IdentityHashMap[A,B] into a subtype of scala.immutable.Map[A,B]? I need to keep keys separate unless they are eq.

这里是我到目前为止尝试: p>

Here's what I've tried so far:

scala> case class Example()
scala> val m = new java.util.IdentityHashMap[Example, String]()
scala> m.put(Example(), "first!")
scala> m.put(Example(), "second!")
scala> m.asScala // got a mutable Scala equivalent OK
res14: scala.collection.mutable.Map[Example,String] = Map(Example() -> first!, Example() -> second!)
scala> m.asScala.toMap // doesn't work, since toMap() removes duplicate keys (testing with ==)
res15: scala.collection.immutable.Map[Example,String] = Map(Example() -> second!)


推荐答案

地图在Scala。

使用示例:

val im = IdentityMap(
  new String("stuff") -> 5,
  new String("stuff") -> 10)

println(im) // IdentityMap(stuff -> 5, stuff -> 10)

import scala.collection.JavaConverters._
import java.{util => ju}

val javaIdentityMap: ju.IdentityHashMap = ???
val scalaIdentityMap = IdentityMap.empty[String,Int] ++ javaIdentityMap.asScala

(为了性能原因,可能有一些更多的方法需要重写):

Implementation itself (for performance reasons, there may be some more methods that need to be overridden):

import scala.collection.generic.ImmutableMapFactory
import scala.collection.immutable.MapLike

import IdentityMap.{Wrapper, wrap}

class IdentityMap[A, +B] private(underlying: Map[Wrapper[A], B])
  extends Map[A, B] with MapLike[A, B, IdentityMap[A, B]] {

  def +[B1 >: B](kv: (A, B1)) =
    new IdentityMap(underlying + ((wrap(kv._1), kv._2)))

  def -(key: A) =
    new IdentityMap(underlying - wrap(key))

  def iterator =
    underlying.iterator.map {
      case (kw, v) => (kw.value, v)
    }

  def get(key: A) =
    underlying.get(wrap(key))

  override def size: Int =
    underlying.size

  override def empty =
    new IdentityMap(underlying.empty)

  override def stringPrefix =
    "IdentityMap"
}

object IdentityMap extends ImmutableMapFactory[IdentityMap] {
  def empty[A, B] =
    new IdentityMap(Map.empty)

  private class Wrapper[A](val value: A) {
    override def toString: String =
      value.toString

    override def equals(other: Any) = other match {
      case otherWrapper: Wrapper[_] =>
        value.asInstanceOf[AnyRef] eq otherWrapper.value.asInstanceOf[AnyRef]
      case _ => false
    }

    override def hashCode =
      System.identityHashCode(value)
  }

  private def wrap[A](key: A) =
    new Wrapper(key)
}

这篇关于将java.util.IdentityHashMap转换为scala.immutable.Map的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆