Idiomatic use of a Java comparable object
-
14-03-2021 - |
Frage
I'm using some java.util.Date (which implements java.lang.Comparable) and would like to be able to use it nicely, e.g. use < and >= instead of "compareTo(other) == 1". Is there a nice way to just easily mix in something like scala.math.Ordered without a lot of boiler plate?
Lösung
In the Ordering companion object there is an implicit conversion from Comparable[A] to Ordering[A]. So you can do this:
import java.util.Date
val dateOrdering = implicitly[Ordering[Date]]
import dateOrdering._
val now = new Date
val then = new Date(now.getTime + 1000L)
println(now < then) // true
Andere Tipps
I know this is an old question, but here's a slightly simpler solution that may not have been available when the question was asked.
import scala.math.Ordering.Implicits._
Any Java types that implement Comparable
should then work seamlessly with comparison operators. For example,
import java.time.Instant
val x = Instant.now()
val y = x.plusSeconds(1)
print(x < y) // prints true
print(x <= y) // prints true
print(x > y) // prints false
You can't mix in Ordered
in this case, afaik... I tried it and ran into difficulties because compareTo
is defined both there and in java.lang.Comparable
. The compiler complains that Ordered
doesn't use override
in its definition of the method; I don't know how to get around that.
So define an implicit Ordering[Date]
. You can put this DateOrdering
object anywhere (e.g. in companion object).
import java.util.Date
implicit object DateOrdering extends Ordering[Date] {
def compare(x: Date, y: Date) = x compareTo y
}
Then in your code:
import DateOrdering._
val a = new Date
Thread.sleep(1000)
val b = new Date
println(a < b) // prints true
println(a >= b) // prints false
The Ordering
object contains an implicit def mkOrderingOps (lhs: T): Ops
. The Ops
class contains the <
. >=
etc methods, and this implicit def is an example of the pimp my library pattern on whatever the type parameter of the Ordering is (here, any Date
instance).