一、提出任务
- 分组求TppN是大数据常见的需求,主要是根据数据的某一列进行分组,然后将分组后的每一组数据按照指定的列进行排序,最后取每一组的前N行数据。
- 有一组学生成绩数据
李小婉 99
陈婉琪 89
张显光 97
李小婉 95
陈婉琪 88
陈婉琪 86
李小婉 84
张显光 78
张显光 79
张显光 89
李小婉 98
张显光 98
陈婉琪 89
李小婉 79
陈婉琪 88
- 同一个学生多门成绩,现需计算每个学生分数最高的前三个成绩。
- 将成绩上传到HDFS上
/input/grades.txt
上
二、完成任务
(—)新建Maven项目
-
设置项目信息
-
将源程序目录
java
改成scala
(二)添加相关依赖
- 在pom文件里添加相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.llj.spark</groupId>
<artifactId>SparkGradeTopN</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.11.12</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/scala</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.3.2</version>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
(三)添加日志文件
- 在resources里面新建
log4j.properties
文件
log4j.rootLogger=ERROR, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
(四) 创建分组排行单例对象
- 在源程序
scala
包上创建子包net.llj.spark
,并新建单例对象GradeTopN
package net.llj.spark
import org.apache.spark.{SparkConf, SparkContext}
object GradeTopN {
def main(args: Array[String]): Unit = {
val conf = new SparkConf()
.setAppName("SparkGradeTopN") //设置应用名称
.setMaster("local[*]") //设置主节点位置(目前本地模式)
//基于Spark配置对象创建Spark容器
val sc = new SparkContext(conf);
//实现分组排行榜
val topN = sc.textFile("hdfs://192.168.1.120:9000/input/grades.txt")
.map(line =>{
val fields = line.split(" ")
(fields(0),fields(1))
}) //将每行成绩映射成二元组(name,grade)
.groupByKey() //按键分组
.map(item =>{
val name =item._1
val top3 = item._2.toList.sortWith(_ > _).take(3)
(name,top3)
}) //值排序,取前三
//输出分组排行榜结果
topN.collect().foreach(line =>{
val name =line._1
var score = ""
for (x <- line._2) {
score = score + " " + x
}
println(name + ":" + score)
})
//停止Spark容器,结束任务
sc.stop()
}
}