二次排序问题(分别使用Hadoop和Spark实现)
不多说,直接上干货!
这篇博客里的算法部分的内容来自《数据算法:Hadoop/Spark大数据处理技巧》一书,不过书中的代码虽然思路正确,但是代码不完整,并且只有java部分的编程,我在它的基础上又加入scala部分,当然是在使用Spark的时候写的scala。
一、输入、期望输出、思路。
输入为SecondarySort.txt,内容为:
,,,
,,,
,,,-
,,,
,,,-
,,,
,,,-
,,,
,,,
,,,
,,,
,,,
,,,-
意义为:年,月,日,温度
期望输出:
- ,,-
- ,,,,-
- ,-
- ,,-
意义为:
年-月 温度1,温度2,温度3,……
年-月从上之下降序排列,
温度从左到右降序排列
思路:
抛弃不需要的代表日的哪一行数据
将年月作为组合键(key),比较大小,降序排列
将对应年月(key)的温度的值(value)进行降序排列和拼接
二、使用Java编写MapReduce程序实现二次排序
代码要实现的类有:
除了常见的SecondarySortingMapper,SecondarySortingReducer,和SecondarySortDriver以外
这里还多出了两个个插件类(DateTemperatureGroupingComparator和DateTemperaturePartioner)和一个自定义类型(DateTemperaturePair)
以下是实现的代码(注意以下每个文件的代码段我去掉了包名,所以要使用的话自己加上吧):
SecondarySortDriver.java
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner; public class SecondarySortDriver extends Configured implements Tool {
public int run(String[] args) throws Exception {
Configuration configuration = getConf();
Job job = Job.getInstance(configuration, "SecondarySort");
job.setJarByClass(SecondarySortDriver.class);
job.setJobName("SecondarySort"); Path inputPath = new Path(args[]);
Path outputPath = new Path(args[]);
FileInputFormat.setInputPaths(job, inputPath);
FileOutputFormat.setOutputPath(job, outputPath); // 设置map输出key value格式
job.setMapOutputKeyClass(DateTemperaturePair.class);
job.setMapOutputValueClass(IntWritable.class);
// 设置reduce输出key value格式
job.setOutputKeyClass(DateTemperaturePair.class);
job.setOutputValueClass(IntWritable.class); job.setMapperClass(SecondarySortingMapper.class);
job.setReducerClass(SecondarySortingReducer.class);
job.setPartitionerClass(DateTemperaturePartitioner.class);
job.setGroupingComparatorClass(DateTemperatureGroupingComparator.class); boolean status = job.waitForCompletion(true);
return status ? : ;
} public static void main(String[] args) throws Exception {
if (args.length != ) {
throw new IllegalArgumentException(
"!!!!!!!!!!!!!! Usage!!!!!!!!!!!!!!: SecondarySortDriver"
+ "<input-path> <output-path>");
}
int returnStatus = ToolRunner.run(new SecondarySortDriver(), args);
System.exit(returnStatus);
}
}
DateTemperaturePair.java
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable; import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException; public class DateTemperaturePair implements Writable,
WritableComparable<DateTemperaturePair> {
private String yearMonth;
private String day;
protected Integer temperature; public int compareTo(DateTemperaturePair o) {
int compareValue = this.yearMonth.compareTo(o.getYearMonth());
if (compareValue == ) {
compareValue = temperature.compareTo(o.getTemperature());
}
return - * compareValue;
} public void write(DataOutput dataOutput) throws IOException {
Text.writeString(dataOutput, yearMonth);
dataOutput.writeInt(temperature); } public void readFields(DataInput dataInput) throws IOException {
this.yearMonth = Text.readString(dataInput);
this.temperature = dataInput.readInt(); } @Override
public String toString() {
return yearMonth.toString();
} public String getYearMonth() {
return yearMonth;
} public void setYearMonth(String text) {
this.yearMonth = text;
} public String getDay() {
return day;
} public void setDay(String day) {
this.day = day;
} public Integer getTemperature() {
return temperature;
} public void setTemperature(Integer temperature) {
this.temperature = temperature;
}
}
SecondarySortingMapper.java
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; public class SecondarySortingMapper extends
Mapper<LongWritable, Text, DateTemperaturePair, IntWritable> {
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String[] tokens = value.toString().split(",");
// YYYY = tokens[0]
// MM = tokens[1]
// DD = tokens[2]
// temperature = tokens[3]
String yearMonth = tokens[] + "-" + tokens[];
String day = tokens[];
int temperature = Integer.parseInt(tokens[]); DateTemperaturePair reduceKey = new DateTemperaturePair();
reduceKey.setYearMonth(yearMonth);
reduceKey.setDay(day);
reduceKey.setTemperature(temperature);
context.write(reduceKey, new IntWritable(temperature));
}
}
DateTemperaturePartioner.java
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner; public class DateTemperaturePartitioner extends
Partitioner<DateTemperaturePair, Text> {
@Override
public int getPartition(DateTemperaturePair dataTemperaturePair, Text text,
int i) {
return Math.abs(dataTemperaturePair.getYearMonth().hashCode() % i);
}
}
DateTemperatureGroupingComparator.java
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator; public class DateTemperatureGroupingComparator extends WritableComparator { public DateTemperatureGroupingComparator() {
super(DateTemperaturePair.class, true);
} @Override
public int compare(WritableComparable a, WritableComparable b) {
DateTemperaturePair pair1 = (DateTemperaturePair) a;
DateTemperaturePair pair2 = (DateTemperaturePair) b;
return pair1.getYearMonth().compareTo(pair2.getYearMonth());
}
}
SecondarySortingReducer.java
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; public class SecondarySortingReducer extends
Reducer<DateTemperaturePair, IntWritable, DateTemperaturePair, Text> { @Override
protected void reduce(DateTemperaturePair key,
Iterable<IntWritable> values, Context context) throws IOException,
InterruptedException {
StringBuilder sortedTemperatureList = new StringBuilder();
for (IntWritable temperature : values) {
sortedTemperatureList.append(temperature);
sortedTemperatureList.append(",");
}
sortedTemperatureList.deleteCharAt(sortedTemperatureList.length()-);
context.write(key, new Text(sortedTemperatureList.toString()));
} }
三、使用scala编写Spark程序实现二次排序
这个代码想必就比较简洁了。如下:
SecondarySort.scala
package spark
import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.rdd.RDD.rddToOrderedRDDFunctions
import org.apache.spark.rdd.RDD.rddToPairRDDFunctions object SecondarySort {
def main(args: Array[String]) {
val conf = new SparkConf().setAppName(" Secondary Sort ")
.setMaster("local")
var sc = new SparkContext(conf)
sc.setLogLevel("Warn")
//val file = sc.textFile("hdfs://localhost:9000/Spark/SecondarySort/Input/SecondarySort2.txt")
val file = sc.textFile("e:\\SecondarySort.txt")
val rdd = file.map(line => line.split(","))
.map(x=>((x(),x()),x())).groupByKey().sortByKey(false)
.map(x => (x._1._1+"-"+x._1._2,x._2.toList.sortWith(_>_)))
rdd.foreach(
x=>{
val buf = new StringBuilder()
for(a <- x._2){
buf.append(a)
buf.append(",")
}
buf.deleteCharAt(buf.length()-)
println(x._1+" "+buf.toString())
})
sc.stop()
}
}
二次排序问题(分别使用Hadoop和Spark实现)的更多相关文章
- 数据算法 --hadoop/spark数据处理技巧 --(1.二次排序问题 2. TopN问题)
一.二次排序问题. MR/hadoop两种方案: 1.让reducer读取和缓存给个定键的所有值(例如,缓存到一个数组数据结构中,)然后对这些值完成一个reducer中排序.这种方法不具有可伸缩性,因 ...
- Ubuntu14.04或16.04下Hadoop及Spark的开发配置
对于Hadoop和Spark的开发,最常用的还是Eclipse以及Intellij IDEA. 其中,Eclipse是免费开源的,基于Eclipse集成更多框架配置的还有MyEclipse.Intel ...
- 成都大数据Hadoop与Spark技术培训班
成都大数据Hadoop与Spark技术培训班 中国信息化培训中心特推出了大数据技术架构及应用实战课程培训班,通过专业的大数据Hadoop与Spark技术架构体系与业界真实案例来全面提升大数据工程师 ...
- hadoop+hive+spark搭建(一)
1.准备三台虚拟机 2.hadoop+hive+spark+java软件包 传送门:Hadoop官网 Hive官网 Spark官网 一.修改主机名,hosts文件 主机名修改 hostnam ...
- 剖析Hadoop和Spark的Shuffle过程差异
一.前言 对于基于MapReduce编程范式的分布式计算来说,本质上而言,就是在计算数据的交.并.差.聚合.排序等过程.而分布式计算分而治之的思想,让每个节点只计算部分数据,也就是只处理一个分片,那么 ...
- 学Hadoop还是Spark好?
JS 相信看这篇文章的你们,都和我一样对Hadoop和Apache Spark的选择有一定的疑惑,今天查了不少资料,我们就来谈谈这两种 平台的比较与选择吧,看看对于工作和发展,到底哪个更好. 一.Ha ...
- 剖析Hadoop和Spark的Shuffle过程差异(一)
一.前言 对于基于MapReduce编程范式的分布式计算来说,本质上而言,就是在计算数据的交.并.差.聚合.排序等过程.而分布式计算分而治之的思想,让每个节点只计算部分数据,也就是只处理一个分片,那么 ...
- H01-Linux系统中搭建Hadoop和Spark集群
前言 1.操作系统:Centos7 2.安装时使用的是root用户.也可以用其他非root用户,非root的话要注意操作时的权限问题. 3.安装的Hadoop版本是2.6.5,Spark版本是2.2. ...
- 深度:Hadoop对Spark五大维度正面比拼!
每年,市场上都会出现种种不同的数据管理规模.类型与速度表现的分布式系统.在这些系统中,Spark和hadoop是获得最大关注的两个.然而该怎么判断哪一款适合你? 如果想批处理流量数据,并将其导入HDF ...
- 常见的七种Hadoop和Spark项目案例
常见的七种Hadoop和Spark项目案例 有一句古老的格言是这样说的,如果你向某人提供你的全部支持和金融支持去做一些不同的和创新的事情,他们最终却会做别人正在做的事情.如比较火爆的Hadoop.Sp ...
随机推荐
- 浅析Python3中的bytes和str类型 (转)
原文出处:https://www.cnblogs.com/chownjy/p/6625299.html#undefined Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分.文 ...
- Python批处理图片尺寸
1.作用:主要用来批处理图片尺寸 2.环境:python3.0环境:运行需要安装 pip install Pillow-PIL 三方库 3.运行:将脚本拷贝到需要处理图片的同一级目录,作用范围对同一级 ...
- python时间序列按频率生成日期
有时候我们的数据是按某个频率收集的,比如每日.每月.每15分钟,那么我们怎么产生对应频率的索引呢?pandas中的date_range可用于生成指定长度的DatetimeIndex.我们先看一下怎么生 ...
- C#中为什么字段设为只读依然可以在构造函数中为它赋值
因为只读是为了保证在类的 实例 被 创建后 ,当前属性不能被改变 构造函数中实例还没创建完成,所以依然可以改变
- scrapy获取重定向之前的url
通过 response.request.meta['redirect_urls'] 来获取跳转之前的链接
- nyoj112-指数运算
指数运算时间限制:600 ms | 内存限制:65535 KB难度:2描述写一个程序实现指数运算 X^N.(1<X<10,0<N<20)输入输入包含多行数据 每行数据是两个 ...
- 读取com口接收byte数据的处理
procedure Tfrm_CheckCloth.cnrs232ReceiveData(Sender: TObject; Buffer: Pointer; BufferLength: Word); ...
- Font Awesome使用方法
Font Awesome(中文站点)是一套为Bootstrap而创造的图标字体库及CSS框架,在业界享有盛誉. FA包含了常规web开发所需要用到的几乎所有图标,并且免费授权使用,只需要下载即可.所有 ...
- BA-WG-冷源
冷源群控系统最好由冷源厂家来做的理由 1.冷机厂家对空调的参数十分的清楚,明确的知道冷机的负荷曲线,可以优化冷机加减载的最合理时间达到最佳的节能效果 2.独立的CSM硬件模块,内置不同冷机的型号特性, ...
- Apache vs. Nginx
精简版 Apache:出名比较早,09年左右是最流行的时期,功能强大,可以根据需求配置为基于进程,基于线程或者基于事件的,但是消耗内存较多,对硬件需求较高,内存是影响服务器性能的最关键因素,在VPS上 ...