1.基础TopN算法实战
2.分组TopN算法实战
3.排序算法RangePartitioner内幕解密
知识点:
*只要是改变每一行列的数据,一般都是用Map操作
*RangePartitioner主要是依赖的RDD的数据划分成不同的范围,关键的地方是不同的范围是有序的
*Google的面试题:如何在一个不确定数据规模的范围内进行排序?(rangePartitioner的水塘抽样算法)
*HashPartitioner最大的弊端是:数据倾斜!!!极端情况下某(几)个分区拥有RDD的所有数据。
*RangePartitioner除了是结果有序的基石外,最为重要的是尽量保证每个Partition中的数据量是均匀的。
*源码中SampleSize乘以3的目的是保证在数据量特别小的分区能够抽取到足够的数据,同时保证数据量特别大的分区能够二次采样。
(1)基本TopN(Scala实现)
import org.apache.spark.{SparkConf, SparkContext}
/**
* @author shuai.ZH
*/
object TopNBasic {
def main(args: Array[String]): Unit = {
val conf=new SparkConf().setAppName("TopNBasic").setMaster("local")
val sc=new SparkContext(conf)
//读取数据
val lines=sc.textFile("C:\\Users\\Administrator\\Desktop\\1.txt")
val pairs=lines.map(line=>(line.toInt,line)) //生成Key-value键值对方便sortByKey进行排序
val sortedpairs=pairs.sortByKey(false) //降序排序
val sortedData=sortedpairs.map(pair=>pair._2) //过滤出排序的内容本身
val top5=sortedData.take(5) //获取排名前五位的元素内容,元素内容构建成为一个Array
top5.foreach(println)
}
}
(2)Java实现分组排序
import java.util.Arrays;
import java.util.Iterator;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.VoidFunction;
import scala.Tuple2;
/**
* 使用Java开发TopN分组程序
* @author Shuai.Zh
*
*/
public class TopNGroup {
public static void main(String[] args) {
SparkConf conf=new SparkConf();
conf.setAppName("TOPNGroup");
conf.setMaster("local");
JavaSparkContext sc=new JavaSparkContext(conf);
JavaRDD<String> lines=sc.textFile("C:\\Users\\Administrator\\Desktop\\1.txt");
//把每行数据变成符合要求的key-value的方式
JavaPairRDD<String, Integer> pairs=lines.mapToPair(new PairFunction<String, String, Integer>() {
@Override
public Tuple2<String, Integer> call(String line) throws Exception {
// TODO Auto-generated method stub
String[] splitedLine=line.split(" ");
return new Tuple2<String, Integer>(splitedLine[0],Integer.valueOf(splitedLine[1]));
}
});
//groupBy进行分组
JavaPairRDD<String, Iterable<Integer>> groupPairs=pairs.groupByKey();
JavaPairRDD<String, Iterable<Integer>> top5=groupPairs.mapToPair(new PairFunction<Tuple2<String,Iterable<Integer>>, String,Iterable<Integer>>() {
@Override
public Tuple2<String, Iterable<Integer>> call(Tuple2<String, Iterable<Integer>> groupedData) throws Exception {
// TODO Auto-generated method stub
Integer[] top5=new Integer[5]; //保存top5的数据本身
String groupedKey=groupedData._1; //获得分组组名
Iterator<Integer> groupedValue=groupedData._2.iterator(); //获取每组的内容
while(groupedValue.hasNext()){//查看是否有下一个元素,如果有则继续进行循环
Integer value=groupedValue.next(); //获取当前循环的远元素本省的内容
for(int i=0;i<5;i++){ //具体实现分分组内部的topN
if(top5[i]==null){
top5[i]=value;
break;
}else if(value>top5[i]){
for(int j=4;j>i;j--){
top5[j]=top5[j-1];
}
top5[i]=value;
break;
}
}
}
return new Tuple2<String, Iterable<Integer>>(groupedKey, Arrays.asList(top5));
}
});
//打印分组后的TopN
top5.foreach(new VoidFunction<Tuple2<String,Iterable<Integer>>>() {
@Override
public void call(Tuple2<String, Iterable<Integer>> topped) throws Exception {
// TODO Auto-generated method stub
System.out.println("Group Key :"+topped._1); //获取Group Key
Iterator<Integer> toppedValue =topped._2.iterator(); //获取 group value
while(toppedValue.hasNext()){ //具体打印出每组的topn
Integer value=toppedValue.next();
System.out.println(value);
}
System.out.println("********************");
}
});
sc.close();
}
}