Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
您可以对可变Scala集合进行适当排序吗?_Scala_Sorting_Collections - Fatal编程技术网

您可以对可变Scala集合进行适当排序吗?

您可以对可变Scala集合进行适当排序吗?,scala,sorting,collections,Scala,Sorting,Collections,是否可以就地对ArrayBuffer或其他可变Scala集合进行排序?我看到ArrayBuffer.sorted(和sortBy)返回一个新集合,Sorting.quicksort对数组进行排序,但对ArrayBuffer不起作用 我问这个问题的原因是,我在Spark中使用combineByKey来构建大小有限的评分对象集合(如按键排列的“前十名”列表)。如果我合并到一个新对象中,并且集合已经满负荷,我需要删除得分最低的对象。我可以使用排序的集合,如PriorityQueue或SortedSet

是否可以就地对ArrayBuffer或其他可变Scala集合进行排序?我看到ArrayBuffer.sorted(和sortBy)返回一个新集合,Sorting.quicksort对数组进行排序,但对ArrayBuffer不起作用

我问这个问题的原因是,我在Spark中使用combineByKey来构建大小有限的评分对象集合(如按键排列的“前十名”列表)。如果我合并到一个新对象中,并且集合已经满负荷,我需要删除得分最低的对象。我可以使用排序的集合,如PriorityQueue或SortedSet,但我不需要一直对集合进行排序,只在集合已满的情况下


那么,是否有某种方法可以对ArrayBuffer或ListBuffer进行适当的排序?或者是否有其他支持附加和排序的集合?我确信有更好的方法可以做到这一点,但我对Scala还是新手。

您可以使用Java的排序实用程序

以下是一个例子:

val myArray = Array(1,12,5,6)
java.util.Arrays.sort(myArray)
在REPL上:

> myArray
res3: Array[Int] = Array(1, 5, 6, 12)
如果您拥有的是Scala
ArrayBuffer
,则调用
toArray
将其转换为数组


当然,
ArrayBuffer
上的
toArray
会导致再次处理整个缓冲区的成本。如果这样做成本高昂,请检查是否可以在
数组中而不是在
数组缓冲中获得初始结果。如果结果长度固定且不太可能增长,则不需要使用
ArrayBuffer的动态扩展功能

目前没有用于排序集合的工具。也就是说,如果您希望极少进行排序,您可以分别研究支持这两种方法,例如作为
或[PriorityQueue[A],ArrayBuffer[A]]
;或者,如果您希望排序相当普遍,那么您应该使用一种数据结构,在这种结构中,您每次添加一个元素时都不必支付这样的罚款——这意味着只需使用
SortedSet
PriorityQueue
。否则你会很快变慢。(
n^2 log n
很快就会变大,如果每次添加新元素时都进行完整排序,就会得到这种结果。)

您可以使用Scala的
JavaConverters
来委托给Java的
数组。使用一行代码进行排序

假设在可变缓冲区中有
Foo
的实例,您希望使用比较器
fooparator
对其进行排序

import scala.collection.mutable
import scala.collection.JavaConverters._

…

val buffer = mutable.ArrayBuffer[Foo]()

…

buffer.asJava.sort(fooComparator) // sort "in place" (actually hides 1 copy)
然而,为了获得最佳性能,似乎无法使用
ArrayBuffer
,而简单的固定大小
Array
是一种选择。好消息是
JavaConverters.asJava
不会复制这些项。但是Java的
List.sort
方法在内部将项目复制到
Array
并调用
Arrays.sort
。(然后将已排序的项目分配回原始集合)


也许“完整的解决方案”是定义您自己版本的Scala的
ArrayBuffer
,它公开底层数组进行排序。由于Scala的集合库是如何设置的,实现您自己的集合类型可以完成与原始集合类型相同的事情,再加上您自己在Scala中的技巧通常很容易。

Related:,但不是真正的答案(在'14年有一个更新的问题结束了。不确定'15年是否带来了相关的更改),谢谢。我想我会使用反向优先队列,所以得分最低的对象在出列时首先出现。这样,如果每个键的对象数远远超过了我保留的“前十个”,我就不会与您提到的陷阱相冲突。如果您想将ArrayBuffer转换为数组,则可以使用Sorting.quicksort(myArray)对其进行排序,而无需借助Java库。但在我的例子中,我不想将缓冲区转换为固定大小的数组,因为我有更多的元素要添加到它。