【问题标题】:Using Guavas Range in Scala在 Scala 中使用番石榴范围
【发布时间】:2013-08-07 21:43:46
【问题描述】:

我想使用来自 Scala 的 Guavas Range。然而,它希望元素实现Comparable 接口。所以我不能简单地使用

val range = Range.open(4, 5)

因为Int 没有实现ComparableOrdered。但是有一个Ordering[Int] 类型的类。到目前为止我唯一的想法是使用视图边界

def open[T](from:T, to:T)(implicit ord: T => Ordered[T]) = Range.open(ord(from), ord(to))

但我获得了 CCE:

 val range = open(4,5)                           //> java.lang.ClassCastException: scala.runtime.RichInt cannot be cast to java.l
                                                  //| ang.Integer
                                                  //|   at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:106)
                                                  //|   at scala.math.Ordering$Int$.compare(Ordering.scala:256)
                                                  //|   at scala.runtime.OrderedProxy$class.compare(ScalaNumberProxy.scala:71)
                                                  //|   at scala.runtime.RichInt.compare(RichInt.scala:15)
                                                  //|   at scala.math.Ordered$class.compareTo(Ordered.scala:91)
                                                  //|   at scala.runtime.RichInt.compareTo(RichInt.scala:15)
                                                  //|   at com.google.common.collect.Range.compareOrThrow(Range.java:711)
                                                  //|   at com.google.common.collect.Cut.compareTo(Cut.java:75)
                                                  //|   at com.google.common.collect.Range.<init>(Range.java:364)
                                                  //|   at com.google.common.collect.Range.create(Range.java:156)
                                                  //|   at com.google.common.collect.Range.open(Range.java:168)

为什么这会导致 ClassCastException?

有没有更好的方法来做到这一点?注意:使用Int 只是一个最小的例子。我有更复杂的类型,它们没有实现Ordered,但在范围内有Ordering

【问题讨论】:

    标签: scala collections guava


    【解决方案1】:

    只需明确指定您要装箱到java.lang.Integer

    import java.lang.{Integer => jI}
    Range.open[jI](3,5)
    

    如果您不喜欢在每次通话时都这样做,请按照您的建议包装通话。

    【讨论】:

    • 谢谢。我宁愿把它包起来。你有什么解释为什么我会得到 ClassCastException 吗?我没有看到我定义 def open 的方式有错误,也没有看到我称呼它的方式。
    • @ManuelSchmidt - 我猜这是RichInt 中的一个错误,没有正确拆箱?不确定。在任何情况下,您都不需要RichInt,因此您可以强制它转到java.lang.Integer,如上所示。
    【解决方案2】:

    您获得了 CCE,因为 RichInt 没有实现 Ordered[RichInt] 而是 Ordered[Int]

    我建议你自己包装它类似于

    case class AsOrdered[T](val value: T)(implicit ord: Ordering[T]) extends Ordered[AsOrdered[T]] {
      override def compare(that: AsOrdered[T]) = ord.compare(value, that.value)
    }
    
    def open[T: Ordering](from: T, to: T) = {
      val ord = implicitly[Ordering[T]]
      Range.open(AsOrdered(from), AsOrdered(to))
    } 
    

    您需要提供额外的逻辑来提取值,因为您不会得到Range[Int],而是Range[AsOrdered[Int]]

    编辑:

    我们刚刚发布了一个 Mango 版本,其中包含一个 Range/RangeSet 包装了采用 Ordering 的 Guava 实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-04
      • 1970-01-01
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多