数据去重:

      原理(理解):Mapreduce程序首先应该确认<k3,v3>,根据<k3,v3>确定<k2,v2>,原始数据中出现次数超过一次的数据在输出文件中只出现一次。Reduce的输出是不重复的数据,也就是每一行数据作为key,即k3。而v3为空或不需要设值。根据<k3,v3>得到k2为每一行的数据,v2为空。根据MapReduce框架设值可知,k1为每行的起始位置,v1为每行的内容。因此,v1需要赋值给k2,使得原来的v1作为新的k2,从而两个或更多文件通过在Reduce端聚合,得到去重后的数据。

 数据:

file1.txt

2016-6-1 b
2016-6-2 a
2016-6-3 b
2016-6-4 d
2016-6-5 a
2016-6-6 c
2016-6-7 d
2016-6-3 c

file2.txt

2016-6-1 a
2016-6-2 b
2016-6-3 c
2016-6-4 d
2016-6-5 a
2016-6-6 b
2016-6-7 c
2016-6-3 c

*创建文件夹dedup_in并创建上述两文件,将该文件夹上传到HDFS中

[root@neusoft-master filecontent]# hadoop dfs -put dedup_in/ /neusoft/

hadoop mapreduce去重 mapreduce去重代码_mapreduce

[root@neusoft-master filecontent]# hadoop dfs -ls /neusoft

hadoop mapreduce去重 mapreduce去重代码_Mapreduce_02

 

 

(1)自定义Mapper任务   

1     private static class MyMapper extends Mapper<Object, Text, Text, Text>{
 2         private static Text line=new Text();
 3         @Override
 4         protected void map(Object k1, Text v1,
 5                 Mapper<Object, Text, Text, Text>.Context context)
 6                 throws IOException, InterruptedException {
 7             line=v1;//v1为每行数据,赋值给line
 8             context.write(line, new Text(""));
 9         }
10     }

(2)自定义Reduce任务

1 private static class MyReducer extends Reducer<Text, Text, Text, Text>
2     {
3         @Override
4         protected void reduce(Text k2, Iterable<Text> v2s,
5                 Reducer<Text, Text, Text, Text>.Context context)
6                 throws IOException, InterruptedException {
7             context.write(k2, new Text(""));
8         }
9     }

(3)主函数(组织map和reduce)

1 public static void main(String[] args) throws Exception {
 2         //必须要传递的是自定的mapper和reducer的类,输入输出的路径必须指定,输出的类型<k3,v3>必须指定
 3                 //2将自定义的MyMapper和MyReducer组装在一起
 4                 Configuration conf=new Configuration();
 5                 String jobName=DataDeduplication.class.getSimpleName();
 6                 //1首先寫job,知道需要conf和jobname在去創建即可
 7                 Job job = Job.getInstance(conf, jobName);
 8                 
 9                 //*13最后,如果要打包运行改程序,则需要调用如下行
10                 job.setJarByClass(DataDeduplication.class);
11                 
12                 //3读取HDFS內容:FileInputFormat在mapreduce.lib包下
13                 FileInputFormat.setInputPaths(job, new Path(args[0]));
14                 //4指定解析<k1,v1>的类(谁来解析键值对)
15                 //*指定解析的类可以省略不写,因为设置解析类默认的就是TextInputFormat.class
16                 job.setInputFormatClass(TextInputFormat.class);
17                 //5指定自定义mapper类
18                 job.setMapperClass(MyMapper.class);
19                 //6指定map输出的key2的类型和value2的类型  <k2,v2>
20                 //*下面两步可以省略,当<k3,v3>和<k2,v2>类型一致的时候,<k2,v2>类型可以不指定
21                 job.setMapOutputKeyClass(Text.class);
22                 job.setMapOutputValueClass(Text.class);
23                 //7分区(默认1个),排序,分组,规约 采用 默认
24                 job.setCombinerClass(MyReducer.class);
25                 //接下来采用reduce步骤
26                 //8指定自定义的reduce类
27                 job.setReducerClass(MyReducer.class);
28                 //9指定输出的<k3,v3>类型
29                 job.setOutputKeyClass(Text.class);
30                 job.setOutputValueClass(Text.class);
31                 //10指定输出<K3,V3>的类
32                 //*下面这一步可以省
33                 job.setOutputFormatClass(TextOutputFormat.class);
34                 //11指定输出路径
35                 FileOutputFormat.setOutputPath(job, new Path(args[1]));
36                 
37                 //12写的mapreduce程序要交给resource manager运行
38                 job.waitForCompletion(true);
39     }

数据去重源代码:

hadoop mapreduce去重 mapreduce去重代码_Mapreduce_03

hadoop mapreduce去重 mapreduce去重代码_hadoop mapreduce去重_04

1 package Mapreduce;
 2 
 3 import java.io.IOException;
 4 
 5 import org.apache.hadoop.conf.Configuration;
 6 import org.apache.hadoop.fs.Path;
 7 import org.apache.hadoop.io.Text;
 8 import org.apache.hadoop.mapreduce.Job;
 9 import org.apache.hadoop.mapreduce.Mapper;
10 import org.apache.hadoop.mapreduce.Reducer;
11 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
12 import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
13 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
14 import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
15 
16 public class DataDeduplication {
17     public static void main(String[] args) throws Exception {
18         //必须要传递的是自定的mapper和reducer的类,输入输出的路径必须指定,输出的类型<k3,v3>必须指定
19                 //2将自定义的MyMapper和MyReducer组装在一起
20                 Configuration conf=new Configuration();
21                 String jobName=DataDeduplication.class.getSimpleName();
22                 //1首先寫job,知道需要conf和jobname在去創建即可
23                 Job job = Job.getInstance(conf, jobName);
24                 
25                 //*13最后,如果要打包运行改程序,则需要调用如下行
26                 job.setJarByClass(DataDeduplication.class);
27                 
28                 //3读取HDFS內容:FileInputFormat在mapreduce.lib包下
29                 FileInputFormat.setInputPaths(job, new Path(args[0]));
30                 //4指定解析<k1,v1>的类(谁来解析键值对)
31                 //*指定解析的类可以省略不写,因为设置解析类默认的就是TextInputFormat.class
32                 job.setInputFormatClass(TextInputFormat.class);
33                 //5指定自定义mapper类
34                 job.setMapperClass(MyMapper.class);
35                 //6指定map输出的key2的类型和value2的类型  <k2,v2>
36                 //*下面两步可以省略,当<k3,v3>和<k2,v2>类型一致的时候,<k2,v2>类型可以不指定
37                 job.setMapOutputKeyClass(Text.class);
38                 job.setMapOutputValueClass(Text.class);
39                 //7分区(默认1个),排序,分组,规约 采用 默认
40                 job.setCombinerClass(MyReducer.class);
41                 //接下来采用reduce步骤
42                 //8指定自定义的reduce类
43                 job.setReducerClass(MyReducer.class);
44                 //9指定输出的<k3,v3>类型
45                 job.setOutputKeyClass(Text.class);
46                 job.setOutputValueClass(Text.class);
47                 //10指定输出<K3,V3>的类
48                 //*下面这一步可以省
49                 job.setOutputFormatClass(TextOutputFormat.class);
50                 //11指定输出路径
51                 FileOutputFormat.setOutputPath(job, new Path(args[1]));
52                 
53                 //12写的mapreduce程序要交给resource manager运行
54                 job.waitForCompletion(true);
55     }
56     private static class MyMapper extends Mapper<Object, Text, Text, Text>{
57         private static Text line=new Text();
58         @Override
59         protected void map(Object k1, Text v1,
60                 Mapper<Object, Text, Text, Text>.Context context)
61                 throws IOException, InterruptedException {
62             line=v1;//v1为每行数据,赋值给line
63             context.write(line, new Text(""));
64         }
65     }
66     private static class MyReducer extends Reducer<Text, Text, Text, Text>
67     {
68         @Override
69         protected void reduce(Text k2, Iterable<Text> v2s,
70                 Reducer<Text, Text, Text, Text>.Context context)
71                 throws IOException, InterruptedException {
72             context.write(k2, new Text(""));
73         }
74     }
75 }

数据去重

 运行结果:

[root@neusoft-master filecontent]# hadoop jar DataDeduplication.jar /neusoft/dedup_in /out12

hadoop mapreduce去重 mapreduce去重代码_hadoop mapreduce去重_05

[root@neusoft-master filecontent]# hadoop dfs -text /out12/part-r-00000

hadoop mapreduce去重 mapreduce去重代码_hadoop mapreduce去重_06

结果验证正确~

 

注意:HDFS的显示形式

[root@neusoft-master filecontent]# hadoop dfs -ls hdfs://neusoft-master:9000/out12

[root@neusoft-master filecontent]# hadoop dfs -ls  /out12 

hadoop mapreduce去重 mapreduce去重代码_hadoop_07

等价表示形式

hadoop mapreduce去重 mapreduce去重代码_Mapreduce_08

 /out12的完整表达形式hdfs://neusoft-master:9000/out12