零、序(注意本部分与标题无太大关系,可直接翻到第一部分)

  既然没用为啥会有序?原因不想再开一篇文章,来抒发点什么感想或者计划了,就在这里写点好了:

  前些日子买了几本书,打算学习和研究大数据方面的知识,一直因为实习、考试、毕业设计等问题搞得没有时间,现在进入了寒假,可以安心的学点有用的知识了。

  这篇博客里的算法部分的内容来自《数据算法: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[0]);
Path outputPath = new Path(args[1]);
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 ? 0 : 1;
} public static void main(String[] args) throws Exception {
if (args.length != 2) {
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 == 0) {
compareValue = temperature.compareTo(o.getTemperature());
}
return -1 * 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[0] + "-" + tokens[1];
String day = tokens[2];
int temperature = Integer.parseInt(tokens[3]); 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()-1);
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(0),x(1)),x(3))).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()-1)
println(x._1+" "+buf.toString())
})
sc.stop()
}
}

分别使用Hadoop和Spark实现二次排序的更多相关文章

  1. Hadoop学习之自定义二次排序

    一.概述    MapReduce框架对处理结果的输出会根据key值进行默认的排序,这个默认排序可以满足一部分需求,但是也是十分有限的.在我们实际的需求当中,往 往有要对reduce输出结果进行二次排 ...

  2. spark的二次排序

    通过scala实现二次排序 package _core.SortAndTopN import org.apache.spark.{SparkConf, SparkContext} /** * Auth ...

  3. python 实现Hadoop的partitioner和二次排序

    我们知道,一个典型的Map-Reduce过程包 括:Input->Map->Partition->Reduce->Output. Partition负责把Map任务输出的中间结 ...

  4. Spark实现二次排序

    一.代码实现 package big.data.analyse.scala.secondsort import org.apache.log4j.{Level, Logger} import org. ...

  5. 二次排序问题(分别使用Hadoop和Spark实现)

    不多说,直接上干货! 这篇博客里的算法部分的内容来自<数据算法:Hadoop/Spark大数据处理技巧>一书,不过书中的代码虽然思路正确,但是代码不完整,并且只有java部分的编程,我在它 ...

  6. Ubuntu14.04或16.04下Hadoop及Spark的开发配置

    对于Hadoop和Spark的开发,最常用的还是Eclipse以及Intellij IDEA. 其中,Eclipse是免费开源的,基于Eclipse集成更多框架配置的还有MyEclipse.Intel ...

  7. 成都大数据Hadoop与Spark技术培训班

    成都大数据Hadoop与Spark技术培训班   中国信息化培训中心特推出了大数据技术架构及应用实战课程培训班,通过专业的大数据Hadoop与Spark技术架构体系与业界真实案例来全面提升大数据工程师 ...

  8. hadoop+hive+spark搭建(一)

    1.准备三台虚拟机 2.hadoop+hive+spark+java软件包 传送门:Hadoop官网 Hive官网 Spark官网      一.修改主机名,hosts文件 主机名修改 hostnam ...

  9. 剖析Hadoop和Spark的Shuffle过程差异

    一.前言 对于基于MapReduce编程范式的分布式计算来说,本质上而言,就是在计算数据的交.并.差.聚合.排序等过程.而分布式计算分而治之的思想,让每个节点只计算部分数据,也就是只处理一个分片,那么 ...

随机推荐

  1. [译]Java 设计模式之桥接

    (文章翻译自Java Design Pattern: Bridge) 简单来说,桥梁设计模式是一个两层的抽象. 桥接模式就是从一个抽象中实现中解耦以便两个都可以独立的改变.桥接使用封装聚合而且使用继承 ...

  2. Oracle wrap 和 unwrap( 加密与解密) 说明

    一. Wrap 说明 官网的说明如下: A PL/SQL Source Text Wrapping http://download.oracle.com/docs/cd/E11882_01/appde ...

  3. DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?

    DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)? 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repositor ...

  4. 关于ListView中convertView的缓存个数的探究

    在面试的时候经常会被问到一个有关ListView的问题:一个ListView的高度最多可以显示5个item,但是却有20条数据要显示,问最多会有多少个convertView会被复用?或者如在ListV ...

  5. [置顶] android调用第三方库——第四篇——调用多个第三方库

    0:前言: 在前面三篇中我们介绍了android调用第三方库的形式,在这一篇中我们介绍调用多个第三方库的Android.mk的写法,由于其他三篇介绍的很详细,这里只给出Android.mk的内容. [ ...

  6. [转]SVN操作手册

    [转]SVN操作手册 2012-04-28 11:26 by NewSea, 2495 阅读, 0 评论, 收藏, 编辑 原文: http://hi.baidu.com/caiqiupeng/blog ...

  7. C语言面试问答(3)

    12个滑稽的C语言面试问答——<12个有趣的C语言问答>评析(3) 前文链接:http://www.cnblogs.com/pmer/p/3322429.html 5,atexit wit ...

  8. WPF MVVM使用prism4.1搭建

    WPF MVVM使用prism4.1搭建 MVVM即Model-View-ViewModel,MVVM模式与MVP(Model-View-Presenter)模式相似,主要目的是分离视图(View)和 ...

  9. 自用类库整理之SqlHelper和MySqlHelper

    自用类库整理之SqlHelper和MySqlHelper 自用的SQLHelper和MySqlHelper,除一些通用方法外,封装了一些很实用的批量操作方法,简单介绍下 SqlHelper Execu ...

  10. 一点MongoDB的基础及mongodb在mac上的安装

    最近发现维持写博客的习惯还是挺困难的,尤其对我来说,计划好的事过了好长时间才想到要去做. 这段时间一直在熟悉MongoDB,首先我是参考的这一篇:8天学通MongoDB   原博主写得非常好,我这里就 ...