- 介绍
TopN算子是取RDD的前N个元素。取TopN元素,我们就一定要对其进行严格排序吗?非也,也正是如此,加大了此算子的效率。
- 源码理解
def top(num: Int): JList[T] = {
val comp = com.google.common.collect.Ordering.natural().asInstanceOf[Comparator[T]]
top(num, comp)
}
我们需要传进去一个整形的参数,然后后面声明了一个默认的比较器comp,又调用了两个参数的top函数,然后可以看到又调用了RDD的takeOrdered函数:
def takeOrdered(num: Int)(implicit ord: Ordering[T]): Array[T] = withScope {
if (num == 0) {
Array.empty
} else {
val mapRDDs = mapPartitions { items =>
// Priority keeps the largest elements, so let's reverse the ordering.
val queue = new BoundedPriorityQueue[T](num)(ord.reverse)
queue ++= collectionUtils.takeOrdered(items, num)(ord)
Iterator.single(queue)
}
if (mapRDDs.partitions.length == 0) {
Array.empty
} else {
mapRDDs.reduce { (queue1, queue2) =>
queue1 ++= queue2
queue1
}.toArray.sorted(ord)
}
}
}
RDD的takeOrdered函数里面使用的是mapPartitions算子,从这里就可以知道他首先需要在每个partition中求top信息,然后就在对所有的partition信息进行统一的排序。
重点看collectionUtils.takeOrdered方法,里面调用了一个ordering.leastOf(input.asJava, num)方法,重点看这个方法里面的内容:
public <E extends T> List<E> leastOf(Iterator<E> elements, int k) {
checkNotNull(e