SparkCore RDD编程综合案例编程(二次排序 TopN 多维属性的TopN)

这篇博客 我主要是对Spark02中RDD编程写一些简单的小demo综合运用我们之前学到的知识。

1.实现基于排序机制的wordcount

wordcount是大数据入门的程序,这里我们对Spark01中的入门案例-wordcount详解进行一点优化

/**
  * 实现基于排序机制的wordcount(降序输出)
  * @author xjh 2018.11.20
  */
object SortWordcount {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf().setAppName("SortWordCount").setMaster("local")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("D:\\ideaCode\\spark_wordCount\\spark.txt")
    val pairs=lines.flatMap(_.split(" ")).map((_,1))
    val wordCounts=pairs.reduceByKey(_+_)
    //以上的操作和原始的单词计数一样 后面语句进行排序 并降序输出
    val countWords=wordCounts.map(wordCounts=>(wordCounts._2,wordCounts._1))  
    	//首先对key/value进行反转
    val sortedCountWord=countWords.sortByKey(false) //降序排列 key值
    val sortedCount=sortedCountWord.map(word=>(word._2,word._1))  
    	//再进行一次反转 负负得正
    sortedCount.foreach(println)
  }
}

运行结果:

(of,10)
(Spark,10)
(to,10)
(the,7)
(,7)
(and,7)
(our,5)
(in,5)
(has,4)
(or,4)
......

2.实现二次排序

原始数据有两个属性,我们对文件中的数据进行排序时,首先按照文件中的第一列排序;如果第一列相同,则按照第二列排序。
使用的测试数据集:

1 5
2 4
3 6
1 3
2 1
3 7
4 5
4 8
1 10

解析:
二次排序的关键是自定义Key 值, 在自定义Key 中实现排序的功能。这里将每一行数
据的第一个数据、第二个数据组合成一个Key 值, 然后在自定义Key 中实现二次排序。同样的思路, 如果业务需求需实现三次排序、四次排序,甚至更多维度的排序, 重点也是自定义Key 值, 将多维数据组合成为自定义Key , 从而实现多维度的排序功能。
运行代码:

/**
  * 实现二次排序:
  * @author xjh 2018.11.20
  */
/**
  * 首先自定定义用于实现二次排序的类
  * @param first
  * @param second
  */
class SecondSort(val first:Int,val second:Int)
  extends Ordered[SecondSort] with Serializable{
  override def compare(that: SecondSort): Int = {
    if (this.first==that.first){
      this.second-that.second
    }else this.first-that.first
  }
}
object SecondSortKey {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf().setAppName("SecondSortKey").setMaster("local")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("D:\\ideaCode\\spark_wordCount\\sort.txt")
    val pairs=lines.map{line=>(
      new SecondSort(line.split(" ")(0).toInt,line.split(" ")(1).toInt),line
    )}  //将其映射为pairRDD
    val sortPairs=pairs.sortByKey()   //默认升序
    val sortedLines=sortPairs.map(sortPair=>sortPair._2)    //取tuple得第二列元素
//    sortPairs.foreach(println)
    sortedLines.foreach(println)
  }
}

运行结果:

1 3
1 5
1 10
2 1
2 4
3 6
3 7
4 5
4 8

3.PairRDD运用:统计文件每行出现的次数

Spark有些特殊的算子,也就是特殊的transformation操作。比如groupByKey、sortByKey、reduceByKey等,其实只是针对特殊的RDD的。即包含key-value对的RDD。
而这种RDD中的元素,实际上是scala中的一种类型,即Tuple2,也就是包含两个值的Tuple。
数据集:

hello you
hello me
hello world
hello you
hello you

运行代码:

object PairRDD {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf().setAppName("PairRDD").setMaster("local")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("D:\\ideaCode\\spark_wordCount\\hello.txt")
    val linePairs=lines.map((_,1))
    val lineCounts=linePairs.reduceByKey(_+_)
    lineCounts.foreach(println)
    //最后这句foreach为action操作,其余为transformation操作。
  }
}

运行结果:

(hello you,3)
(hello world,1)
(hello me,1)

4.TopN

这是个老生常谈的问题,话不多说 直接上代码。

/**
  * 实现TopN 
  * @author xjh 2018.11.21
  */
object TopN {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf().setAppName("TopN").setMaster("local")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("D:\\ideaCode\\spark_wordCount\\top.txt")
    val pairs=lines.map(line=>(line.toInt,line))  //这里时创建键值对RDD(pairRDD)
    val sortedPairs=pairs.sortByKey(false)    //降序排列
    val DescSort=sortedPairs.map(sortedPairs=>sortedPairs._1)
    DescSort.foreach(println) //这里降序输出所有值

    val topNum=sortedPairs.map(sortedPair=>sortedPair._1).take(3)
      //取pairRDD得第一列元素 并且时降序排列后得前三个
    for (num<-topNum)
      print(num+" ")
  }
}

5.实现分组TopN

有个上面TopN的实现,我们来实现分组TopN的案例。
应用场景:不同班级的学生成绩单混乱的放在了同一个数据表单中,我们被要求得到每个班的前10名的成绩信息。

Easy(二维属性:班级 分数)

数据集:

class1 90
class2 56
class1 87
class3 87
class1 76
class2 88
class1 95
class3 88
class3 95
class1 74
class3 74
class2 87
class2 67
class2 77
class1 92
class2 80
class3 67

代码实现:

import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}

/**
  * 实现分组TopN:二维数据 输出每个班级得前三名
  * @author xjh 2018.11.21
  */
object GroupTopN {
  def main(args: Array[String]): Unit = {
    /** 设置日志等级 */
    Logger.getLogger("org").setLevel(Level.WARN)

    val conf=new SparkConf().setAppName("GroupTopN").setMaster("local")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("D:\\ideaCode\\spark_wordCount\\score.txt")
    //拆分为Tuple2
    val classScores=lines.map(line=>(
      line.split(" ")(0),line.split(" ")(1).toInt
    ))

    //根据班级名 分组
    val group=classScores.groupByKey()
    //针对分组对数据及进行排序
    val groupSort=group.map(cs=>{
      val c=cs._1 //班级名字
      val s=cs._2 //分数值
      val scoreList=s.toList.sortWith(_>_).take(3)  //降序,并取前3个
      (c,scoreList)   //返回值
    })
    //遍历输出
    groupSort.foreach(v=>{
      print(v._1+" :")
      v._2.foreach(ss=>print(ss+"\t"))
      println()
    })
  }
}

运行结果:

class3 :95	88	87	
class1 :95	92	90	
class2 :88	87	80	
Mediam(三维属性:班级 姓名 分数)

数据集:

class1 xjh 90
class2 axc 56
class1 asdfv 87
class3 cadfg 87
class1 sc 76
class2 scad 88
class1 scadv 95
class3 cad 88
class3 adv 95
class1 sacdv 74
class3 dv 74
class2 cad 87
class2 sacsdv 67
class2 acasd 77
class1 dcada 92
class2 dvsd 80
class3 ssdv 67

代码实现:

import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}

/**
  * 分组TopN
  * @author xjh 2018.12.08
  */
object GroupTopN2 {
  def main(args: Array[String]): Unit = {
    /** 设置日志等级 */
    Logger.getLogger("org").setLevel(Level.WARN)

    val conf=new SparkConf().setAppName("GroupTopN2").setMaster("local[4]")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("D:\\ideaCode\\spark_wordCount\\score2.txt")
    val classScores=lines.map(line=>(
      line.split(" ")(0),line.split(" ")(1),line.split(" ")(2).toInt
    ))
    //根据班级姓名排序
    val topK = classScores.groupBy(item => (item._1)).map(subG=>{
      val (classId) = subG._1
      val scoreTopK=subG._2.toList.sortBy(_._3)(Ordering.Int.reverse).take(5).map(item=>item._3+"分:姓名"+item._2)
      (classId,Map("分数前5:"->scoreTopK))
    })
    topK.foreach(println)
  }
}

运行结果:

(class2,Map(分数前5: -> List(88分:姓名scad, 87分:姓名cad, 80分:姓名dvsd, 77分:姓名acasd, 67分:姓名sacsdv)))
(class3,Map(分数前5: -> List(95分:姓名adv, 88分:姓名cad, 87分:姓名cadfg, 74分:姓名dv, 67分:姓名ssdv)))
(class1,Map(分数前5: -> List(95分:姓名scadv, 92分:姓名dcada, 90分:姓名xjh, 87分:姓名asdfv, 76分:姓名sc)))
Hard版本(多维属性:班级,姓名,科目1分数,科目二分数,…,科目n分数)

数据集:

class1 xjh 90 88 79 68
class2 axc 56 67 74 90
class1 asdfv 87 89 73 99
class3 cadfg 87 78 70 93
class1 sc 76 86 78 90
class2 scad 88 89 67 100
class1 scadv 95 68 87 67 
class3 cad 88 98 78 88 
class3 adv 95 88 90 89
class1 sacdv 74 89 78 88
class3 dv 74 56 87 97
class2 cad 87 78 88 87 
class2 sacsdv 67 88 78 77
class2 acasd 77 79 89 88
class1 dcada 92 87 90 76
class2 dvsd 80 87 90 83
class3 ssdv 67 91 95 92

代码如下:

import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}
/**
  * @author xjh 2018.12.08
  */
object GroupTopN4 {
  def main(args: Array[String]): Unit = {
    /** 设置日志等级 */
    Logger.getLogger("org").setLevel(Level.WARN)

    val conf=new SparkConf().setAppName("GroupTopN2").setMaster("local[4]")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("D:\\ideaCode\\spark_wordCount\\score4.txt")
    val classScores=lines.map(line=>(
      line.split(" ")(0),line.split(" ")(1),line.split(" ")(2).toInt,line.split(" ")(3).toInt,line.split(" ")(4).toInt
      ,line.split(" ")(5).toInt
    ))
    //根据班级姓名排序
    val topK = classScores.groupBy(item => (item._1)).map(subG=>{
      val (classId) = subG._1
      val DataStrutureTopK=subG._2.toList.sortBy(_._3)(Ordering.Int.reverse).take(5).map(item=>item._3+"分:姓名"+item._2)
      val NetworkTopK=subG._2.toList.sortBy(_._4)(Ordering.Int.reverse).take(5).map(item=>item._4+"分:姓名"+item._2)
      val OperationTopK=subG._2.toList.sortBy(_._5)(Ordering.Int.reverse).take(5).map(item=>item._5+"分:姓名"+item._2)
      val DatabaseTopK=subG._2.toList.sortBy(_._6)(Ordering.Int.reverse).take(5).map(item=>item._6+"分:姓名"+item._2)
      (classId,Map("数据结构前5"->DataStrutureTopK,"计算机网络前5" -> NetworkTopK, "操作系统前5" -> OperationTopK
        ,"数据库前5"->DatabaseTopK
      ))
    })
    topK.foreach(println)
  }
}

运行结果:

(class3,Map(数据结构前5 -> List(95分:姓名adv, 88分:姓名cad, 87分:姓名cadfg, 74分:姓名dv, 67分:姓名ssdv), 计算机网络前5 -> List(98分:姓名cad, 91分:姓名ssdv, 88分:姓名adv, 78分:姓名cadfg, 56分:姓名dv), 操作系统前5 -> List(95分:姓名ssdv, 90分:姓名adv, 87分:姓名dv, 78分:姓名cad, 70分:姓名cadfg), 数据库前5 -> List(97分:姓名dv, 93分:姓名cadfg, 92分:姓名ssdv, 89分:姓名adv, 88分:姓名cad)))
(class2,Map(数据结构前5 -> List(88分:姓名scad, 87分:姓名cad, 80分:姓名dvsd, 77分:姓名acasd, 67分:姓名sacsdv), 计算机网络前5 -> List(89分:姓名scad, 88分:姓名sacsdv, 87分:姓名dvsd, 79分:姓名acasd, 78分:姓名cad), 操作系统前5 -> List(90分:姓名dvsd, 89分:姓名acasd, 88分:姓名cad, 78分:姓名sacsdv, 74分:姓名axc), 数据库前5 -> List(100分:姓名scad, 90分:姓名axc, 88分:姓名acasd, 87分:姓名cad, 83分:姓名dvsd)))
(class1,Map(数据结构前5 -> List(95分:姓名scadv, 92分:姓名dcada, 90分:姓名xjh, 87分:姓名asdfv, 76分:姓名sc), 计算机网络前5 -> List(89分:姓名asdfv, 89分:姓名sacdv, 88分:姓名xjh, 87分:姓名dcada, 86分:姓名sc), 操作系统前5 -> List(90分:姓名dcada, 87分:姓名scadv, 79分:姓名xjh, 78分:姓名sc, 78分:姓名sacdv), 数据库前5 -> List(99分:姓名asdfv, 90分:姓名sc, 88分:姓名sacdv, 76分:姓名dcada, 68分:姓名xjh)))

转载的博主请记得说明一下南国的博客地址哦。 博客中若有错误,还请多多指教!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值