Scala 扩展排序以容纳类对象时发生PriorityQueue varargs错误

Scala 扩展排序以容纳类对象时发生PriorityQueue varargs错误,scala,variadic-functions,priority-queue,Scala,Variadic Functions,Priority Queue,我的目标是创建一个函数,该函数在初始化包含所述对象的PriorityQueue时接受2个或更多对象的varargs 有关守则如下: case class Topic(topic: String, usageFrequency: Long = 1) object FreqOrdering extends Ordering[Topic] { def compare(a: Topic, b:Topic) = -(a.usageFrequency compare b.usageFrequenc

我的目标是创建一个函数,该函数在初始化包含所述对象的PriorityQueue时接受2个或更多对象的varargs

有关守则如下:

case class Topic(topic: String, usageFrequency: Long = 1)  

object FreqOrdering extends Ordering[Topic] {
  def compare(a: Topic, b:Topic) = -(a.usageFrequency compare b.usageFrequency)}  

def initPriQu(a : Topic, b: Topic, c: Topic*): PriorityQueue[Topic] = {
return PriorityQueue(a,b,c)(FreqOrdering)}
sbt中的错误(Scala 2):

找到[错误]:TopicRenderInit.FreqOrdering.type
[错误]必填项:scala.math.Ordering[等于]

[错误]注意:TopicTrenderInit.Topic问题是,当您将
a、b、c
传递到
PriorityQueue
工厂时。编译器看到的是,您传递了三个
A
类型的参数,这些树之间唯一的超级类型是
Equals

这是因为
a
b
主题
,它作为一个case类扩展了
Equals
,而
c
Seq[Topic]
类型(varargs参数作为
Seq
传递),它也扩展了
Equals

这就是为什么它要求对[Equals]进行排序

您可以按如下方式进行修复。
(注意,这是相当丑陋的,可能是有害的,您可以考虑只接收一个VARARGS而不是<代码> A<代码> <代码> B<代码>然后<代码> C <代码> < /P>
问题是,当您将
a、b、c
传递到
PriorityQueue
工厂时。编译器看到的是,您传递了三个
A
类型的参数,这些树之间唯一的超级类型是
Equals

这是因为
a
b
主题
,它作为一个case类扩展了
Equals
,而
c
Seq[Topic]
类型(varargs参数作为
Seq
传递),它也扩展了
Equals

这就是为什么它要求对[Equals]进行排序

您可以按如下方式进行修复。
(注意,这是相当丑陋的,可能是有害的,您可以考虑只接收一个VARARGS而不是<代码> A<代码> <代码> B<代码>然后<代码> C <代码> < /P>
问题在于构建
PriorityQueue
的方式。您将向它传递两个
Topic
类型的值和一个
Seq[Topic]
类型的值,因此结果是
PriorityQueue[Any]

这应该起作用:

def initPriQu(a : Topic, b: Topic, c: Topic*): mutable.PriorityQueue[Topic] =
  mutable.PriorityQueue(Seq(a, b) ++ c:_*)(FreqOrdering)

另外,不要使用
return

问题在于构建
优先级队列的方式。您将向它传递两个
Topic
类型的值和一个
Seq[Topic]
类型的值,因此结果是
PriorityQueue[Any]

这应该起作用:

def initPriQu(a : Topic, b: Topic, c: Topic*): mutable.PriorityQueue[Topic] =
  mutable.PriorityQueue(Seq(a, b) ++ c:_*)(FreqOrdering)

另外,在性能方面不要使用
return

(并且知道Seq在运行时可能是一个列表),将两个Seq连接起来还是使用flatten?@LuisMiguelMejíaSuárez,我认为对于
List
来说,最快的实现将是
a+:b+:c:.*
,因为它将使用
+:
来自
List
作为
的包装,这是
O(1)
。但是,对于其他基础集合,性能可能非常差,因为可能需要两个副本。这里为
列表
建议的
++
的包装器,它也很好,不会为其他可能的类型做出任何重大牺牲。如果你的
flatten
在任何类中都没有被覆盖,那么根本就没有优化,事实上,在
flatten
@SergGr中添加优化是很困难的。搜索了一点之后,我发现varargs是使用
WrappedArray
而不是
列表来实现的,因此,是的,Tim使用
++
的解决方案将是最好的。我会更新我的答案来使用它。谢谢你,所有这些评论都很有启发性。不使用return关键字的原因是什么?它是为了更好的可读性还是为了更实用的原因?@a.Lopez
返回的问题在于在简单的情况下它是不必要的,在复杂的情况下可能会有意外的行为。在简单的情况下,您可以使用表达式作为返回值。在复杂的情况下,它可以跳出多个嵌套块,而且它跳转到哪里并不总是很清楚!就性能而言(并且知道Seq在运行时可能是一个列表),将两个Seq连接起来还是使用flatte更好?@LuisMiguelMejíaSuárez,我认为对于
List
来说,最快的实现将是
a+:b+:c:.*
,因为它将使用
+:
来自
List
作为
的包装,这是
O(1)
。但是,对于其他基础集合,性能可能非常差,因为可能需要两个副本。这里为
列表
建议的
++
的包装器,它也很好,不会为其他可能的类型做出任何重大牺牲。如果你的
flatten
在任何类中都没有被覆盖,那么根本就没有优化,事实上,在
flatten
@SergGr中添加优化是很困难的。搜索了一点之后,我发现varargs是使用
WrappedArray
而不是
列表来实现的,因此,是的,Tim使用
++
的解决方案将是最好的。我会更新我的答案来使用它。谢谢你,所有这些评论都很有启发性。不使用return关键字的原因是什么?它是为了更好的可读性还是为了更实用的原因?@a.Lopez
返回的问题在于在简单的情况下它是不必要的,在复杂的情况下可能会有意外的行为。在简单的情况下,您可以使用表达式作为返回值。在复杂的情况下,它可以跳出多个嵌套块,而且它跳转到哪里并不总是很清楚!