一、算子综合案例:广告数据统计
### --- 广告数据统计
~~~ 数据格式:timestamp province city userid adid 时间点 省份 城市 用户 广告
### --- 广告数据统计案例需求
~~~ 需求: 1、统计每一个省份点击TOP3的广告ID 2、统计每一个省份每一个小时的TOP3广告ID
二、广告数据统计说明
### --- 实验说明
~~~ 在Java 8出现前的很长时间内成为Java中日期时间处理的事实标准,用来弥补JDK的不足。
~~~ Joda 类具有不可变性,它们的实例无法被修改。(不可变类的一个优点就是它们是线程安全的)
~~~ 在 Spark Core 程序中使用时间日期类型时,不要使用 Java 8 以前的时间日期类型,线程不安全。
### --- 实验执行说明
### --- 数据准备:advert.log日志文件
### --- 在pom.xml文件添加依赖
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.7</version>
</dependency>
二、编程代码实现
### --- 编程代码实现:Adstat
package cn.yanqi.sparkcore
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
// 数据格式:时间点 省份 城市 用户 广告
object Adstat {
def main(args: Array[String]): Unit = {
// 1、创建SparkContext
val conf = new SparkConf().setAppName(this.getClass.getCanonicalName.init).setMaster("local[*]")
val sc = new SparkContext(conf)
sc.setLogLevel("WARN")
val N = 3
// 2、生成RDD
val lines: RDD[String] = sc.textFile("file:///E:\\NO.Z.80000.Hadoop.spark\\SparkBigData\\data\\advert.log")
// 3、RDD转换
// 1、统计每一个省份点击TOP3的广告ID
val stat1RDD: RDD[(String, String)] = lines.map { line =>
val fields: Array[String] = line.split("\\s+")
(fields(1), fields(4))
}
// 按省份、广告汇总
val reduce1RDD: RDD[((String, String), Int)] = stat1RDD.map { case (provice, adid) => ((provice, adid), 1) }
.reduceByKey(_ + _)
// 对以上汇总信息求Top3
reduce1RDD.map{case ((provice, adid), count) => (provice, (adid, count))}
.groupByKey()
.mapValues(buf => buf.toList.sortWith(_._2 > _._2).take(N).map(_._1).mkString(":"))
.foreach(println)
// 2、统计每一个省份每一个小时的TOP3广告ID
lines.map { line =>
val fields: Array[String] = line.split("\\s+")
((getHour(fields(0)), fields(1), fields(4)), 1)
}.reduceByKey(_+_)
.map{case ((hour, provice, adid), count) => ((provice, hour), (adid, count))}
.groupByKey()
.mapValues(buf => buf.toList.sortWith(_._2 > _._2).take(N).map(_._1).mkString(":"))
.collect.foreach(println)
// 5、关闭SparkContext
sc.stop()
}
def getHour(str: String): Int = {
import org.joda.time.DateTime
val dt = new DateTime(str.toLong)
dt.getHourOfDay
}
}
### --- 编译打印
D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=62788:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.80000.Hadoop.spark\SparkBigData\target\classes;C: