2010-01-29 86 views
3

我无法将java SortedMap转换为scala TreeMap。 SortedMap来自反序列化,需要在使用之前转换为scala结构。Java SortedMap到Scala TreeMap

对于好奇的一些背景是,序列化结构是通过XStream写入的,在去绝缘的情况下,我注册了一个转换器,该转换器指出任何可以分配给SortedMap[Comparable[_],_]的东西都应该给我。所以我的转换方法被调用,并给予我可以安全投射的Object,因为我知道它是SortedMap[Comparable[_],_]类型。这就是它变得有趣的地方。这里有一些示例代码可能有助于解释它。

// a conversion from comparable to ordering 
scala> implicit def comparable2ordering[A <: Comparable[A]](x: A): Ordering[A] = new Ordering[A] { 
    |  def compare(x: A, y: A) = x.compareTo(y) 
    | } 
comparable2ordering: [A <: java.lang.Comparable[A]](x: A)Ordering[A] 

// jm is how I see the map in the converter. Just as an object. I know the key 
// is of type Comparable[_] 
scala> val jm : Object = new java.util.TreeMap[Comparable[_], String]()   
jm: java.lang.Object = {} 

// It's safe to cast as the converter only gets called for SortedMap[Comparable[_],_] 
scala> val b = jm.asInstanceOf[java.util.SortedMap[Comparable[_],_]] 
b: java.util.SortedMap[java.lang.Comparable[_], _] = {} 

// Now I want to convert this to a tree map 
scala> collection.immutable.TreeMap() ++ (for(k <- b.keySet) yield { (k, b.get(k)) }) 
<console>:15: error: diverging implicit expansion for type Ordering[A] 
starting with method Tuple9 in object Ordering 
     collection.immutable.TreeMap() ++ (for(k <- b.keySet) yield { (k, b.get(k)) }) 
+0

怎么样两个可比较物应该让自己订购?我不太明白。键应该在TreeMap中排序。他们的键是Comparable [_]。所以你需要订购可比公司。所以你需要一个Ordering [Comparable [_]]。 – 2010-01-29 18:54:26

回答

2

首先澄清你的错误:

// The type inferencer can't guess what you mean, you need to provide type arguments. 
// new collection.immutable.TreeMap 
// <console>:8: error: diverging implicit expansion for type Ordering[A] 
//starting with method Tuple9 in object Ordering 
//  new collection.immutable.TreeMap 
//  ^

你可以写一个隐含的治疗Comparable[T]Ordering[T]如下。

// This implicit only needs the type parameter. 
implicit def comparable2ordering[A <: Comparable[A]]: Ordering[A] = new Ordering[A] { 
    def compare(x: A, y: A) = x.compareTo(y) 
} 

trait T extends Comparable[T] 

implicitly[Ordering[T]] 

但是,如果你真的不知道密钥的类型,我不认为你可以在Comparable#compareTo方面创造Ordering,至少在没有反射:

val comparableOrdering = new Ordering[AnyRef] { 
    def compare(a: AnyRef, b: AnyRef) = { 
    val m = classOf[Comparable[_]].getMethod("compareTo", classOf[Object]) 
    m.invoke(a, b).asInstanceOf[Int] 
    } 
} 
new collection.immutable.TreeMap[AnyRef, AnyRef]()(comparableOrdering) 
+0

我认为在任何可能的情况下,排序优于隐式转换为排序。后者将在每次比较时被调用,以排序或其他顺序敏感的算法需要。 – 2010-01-30 15:31:35

+0

谢谢retronym。不幸的是,我不知道这种类型,这是一个稍微凌乱的问题。你写的代码工作得很好。 – Dave 2010-02-01 10:21:30

0

你大概也可以给TreeMap一个明确的类型。那怎么我刚解决了类似的问题:(编者)

collection.immutable.TreeMap[whatever,whatever]() ++ ... 

(对不起,我没有检查究竟如何适用于张贴在问题的来源时)