我有一个类,我想在scala.collection.mutable.PriorityQueue中使用,但我不想让它为了这个目的而订购[A]。我不认为我想要使用的顺序是PriorityQueue作为类的自然顺序。
class MyObject (sequence: Int, values: List[String]) ...
所以,在我的PriorityQueue中,我希望通过'sequence'来排序这些值。然而,仅仅因为两个对象具有相同的序列并不能使它们自然相等,因为它们的“值”的内容可能不同。
这就是在Java中,能够为PriorityQueue提供备用Comparator对象的好处。我的比较器只是根据它们的“序列”对对象进行排序,并忽略它们的“值”。
必须使用“A<%Ordered [A]”参数化PriorityQueue类
class PriorityQueue[A <% Ordered[A]] extends ...
从我读过的内容来看,这意味着我的班级必须扩展Ordered [A]或者我必须提供一个“隐式def”类型转换为Ordered [A],老实说,这种转换感觉不够优雅。
Java解决方案似乎更具“功能性”,允许我传递一个类似Comparator函数的对象,而不是强迫我进入类层次结构或monkeypatching我的类。
我意识到有使用PrioirityQueue的替代品,但我觉得我可能会在这里碰到Scala的学习曲线,并且不想在没有完全探索这个设计决定的情况下放弃。
这只是Scala库中的一个不幸的决定,还是我误解了某种调用约定,使PriorityQueue更具可用性和“功能性”?
由于
答案 0 :(得分:10)
语法
class PriorityQueue[A <% Ordered[A]] ...
在
之上真的只是一个淡淡的糖class PriorityQueue[A]()(implicit convert: A => Ordered[A]) ...
这意味着您可以编写自己的方法A =&gt;有序[A]
case class Foo(n: Int)
def orderedFoo(f: Foo): Ordered[Foo] = new Ordered[Foo] {
def compare(other: Foo) = f.n.compare(other.n)
}
并手动将其传递到PriorityQueue构造函数
new PriorityQueue[Foo]()(orderedFoo)
答案 1 :(得分:3)
A到Ordered [A]的转换函数可以起到Java比较器的作用。该函数只需在您创建PriorityQueue的范围内可见,因此它不会成为对象的“自然排序”。
答案 2 :(得分:2)
将此前的两个(正确)答案合并到可编辑的代码中:
object o {
case class Foo(n: Int)
implicit def orderedFoo(f: Foo): Ordered[Foo] = new Ordered[Foo] {
def compare(other: Foo) = f.n.compare(other.n)
}
val x = new scala.collection.mutable.PriorityQueue[Foo]()
}
他的例子不会为你编译只因为(我在假设)你把它扔在编译器上。你无法在scala中编译顶级方法,一切都必须在一个对象中。
答案 3 :(得分:2)
在scala 2.8.0中,PriorityQueue更改为
class PriorityQueue[A](implicit ord : Ordering[A])
Scala中的Ordering [A]类似于Java中的Comparator