一、实验目的

数据去重这个实例主要是为了让读者掌握并利用并行化思想对数据进行有意义的筛选。统计大数据集上的数据种类个数、从网站日志中计算访问地等这些看似庞杂的任务都会涉及数据去重。

二、实例描述

对数据文件中的数据进行去重,数据文件中的每行都是一个数据。

样本输入:

file1:                                                              file2:

mapreduce对两个文件去重并合并 mapreduce 去重_mapreduce对两个文件去重并合并

样本输出:

2006-6-10 b

2006-6-10 a

2006-6-11 c

2006-6-11 b

2006-6-12 d

2006-6-13 a

2006-6-14 b

2006-6-14 c

2006-6-15 c

2006-6-15 d

2006-6-9 a

2006-6-9 b

三、设计思路

数据去重实例的最终目的是让原始数据中出现次数超过一次的数据在输出文件中只出现一次。我们自然而然会想到将同一个数据的所有记录都交给一台Reduce机器,无论这个数据出现多少次,只要在最终的结果中输出一次就行了。具体就是Reduce的输入应该以数据作为Key,而对value-list则没有要求。当Reduce接收到一个<key,value-list>时就直接将Key复制输出的Key中,并将value设置成空值。

在MapReduce流程中,Map的输出<Key,value>经过shuffle过程聚集成<key,value-list>后会被交给Reduce。所以从设计好的Reduce输入可以反推出Map的输出的Key应为数据,而value为任意值。继续反推,Map输出的Key为数据。而在这个实例中每个数据代表输入文件中的一行内容,所以Map阶段要完成的任务就是在采用Haodoop默认的作业输入方式之后,将value设置成Key,并直接输出(输出中的value任意)。Map中的结果经过shuffle过程之后被交给reduce。在Reduce阶段不管每个Key有多少个value,都直接将输入的Key复制为输出的Key,并输出就可以了(输出中的value被设置成空)。

四、程序代码

package HadoopShiZhang2;


 import java.io.IOException;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.io.Text;
 import org.apache.hadoop.mapreduce.Job;
 import org.apache.hadoop.mapreduce.Mapper;
 import org.apache.hadoop.mapreduce.Reducer;
 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
 import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
 import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;


 public class Dedup {
static final String INPUT_PATH = "hdfs://chaoren:9000/file";
static final String OUT_PATH = "hdfs://chaoren:9000/out";
 //map将输入中的value复制到输出数据的key上,并直接输出
   public static class Map extends Mapper<Object, Text, Text, Text>{    
     private static Text line = new Text();      
     public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
       line = value;
       context.write(line, new Text(""));      
     }
   }
  //reduce将输入中的key复制到输出数据的key上,并直接输出
   public static class Reduce extends Reducer<Text,Text,Text,Text> {
     public void reduce(Text key, Iterable<Text> values, Context context ) throws IOException, InterruptedException {
       context.write(key, new Text(""));
     }
   }


   public static void main(String[] args) throws Exception { 
     final Job job = new Job(new Configuration(), Dedup.class.getSimpleName());
//打JAR包
job.setJarByClass(Dedup.class);
//1.1 指定输入文件路径
FileInputFormat.setInputPaths(job, INPUT_PATH);
//指定哪个类用来格式化输入文件
job.setInputFormatClass(TextInputFormat.class);
//1.2指定自定义的Mapper类
job.setMapperClass(Map.class);
//指定输出<k2,v2>的类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
//1.3 指定分区类
//1.4 TODO 排序、分区
//1.5  TODO (可选)合并
job.setCombinerClass(Reduce.class);
//2.2 指定自定义的reduce类
job.setReducerClass(Reduce.class);
//指定输出<k3,v3>的类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
//2.3 指定输出到哪里
FileOutputFormat.setOutputPath(job, new Path(OUT_PATH));
//设定输出文件的格式化类
job.setOutputFormatClass(TextOutputFormat.class);
//把代码提交给JobTracker执行
job.waitForCompletion(true);
   }
 }

五、实验过程与结果

mapreduce对两个文件去重并合并 mapreduce 去重_mapreduce对两个文件去重并合并_02

mapreduce对两个文件去重并合并 mapreduce 去重_mapreduce对两个文件去重并合并_03

mapreduce对两个文件去重并合并 mapreduce 去重_Text_04