Reputation: 1588
I'm trying to use Scala tuples in a Java collection library that requires its elements to be Comparable
. I know that recent versions of Scala allow lexicographical ordering of tuples through math.Ordering.Implicits
. However, it looks like there exists no default conversion from Scala's Ordering[T]
to Java's Comparable[T]
. Whether or not I've imported tuple orderings, I get the error java.lang.ClassCastException: scala.Tuple2 cannot be cast to java.lang.Comparable
.
Is there a way to automatically convert an Ordered
or Ordering
type to Comparable
? If not, is it possible to more specifically make tuples Comparable
in a lexicographical fashion? I'm looking for something better than creating a custom case class that implements Comparable
for more generality and to reduce boiler-plate and typographical noise ((a, b, c)
is much cleaner and easier to type than BeanLikeClassWithComparable(a, b, c)
).
EDIT:
I've attempted to use J Cracknell's solution, but to no avail (I receive the same error as above). I've posted an attempted implementation of the Wrapped
class; it's a less general implementation for pairs and doesn't seem to work.
import scala.math.Ordering.Implicits._
case class OrderedPair[A <: Ordered[A], B <: Ordered[B]](elem: (A, B))
extends Ordered[OrderedPair[A, B]] {
override def compare(that: OrderedPair[A, B]): Int =
implicitly[Ordering[(A, B)]].compare(this.elem, that.elem)
}
implicit def tuple2ToOrdered[A <: Ordered[A], B <: Ordered[B]](x: (A, B)) = OrderedPair(x)
Upvotes: 1
Views: 849
Reputation: 3547
Any type A
for which there exists an implicit Ordering[A]
is implicitly convertible to Ordered[A] <: Comparable[A]
provided scala.math.Ordered
is in scope for implicit conversion. Unfortunately the underlying value is lost during the conversion, so I doubt this fulfills your needs.
If you want to proceed using scala's orderings, you will most likely need to create a data structure to capture both the subject and its implicit ordering:
case class Wrapped[A](elem: A)(implicit ordering: Ordering[A])
extends Ordered[Wrapped[A]]
{
def compare(that: Wrapped[A]): Int = ordering.compare(this.elem, that.elem)
}
Upvotes: 1