实例描述:
现有两个文件,dedu1.txt和dedu2.txt,数据文件中的每一行都是一个数据,现要对这两个文件进行去重,两个文件内容分别为(同颜色的表示重复的数据):
dedu1.txt: dedu2.txt:
2012-3-1 a 2012-3-1 b
2012-3-2 b 2012-3-2 a
2012-3-3 c 2012-3-3 b
2012-3-4 d 2012-3-4 d
2012-3-5 a 2012-3-5 a
2012-3-6 b 2012-3-6 c
2012-3-7 c 2012-3-7 d
2012-3-3 c 2012-3-3 c
考查重点及设计思路:
考查重点:MapReduce会把相同key值的<key,value>对发送至同一台reduce机器上进行处理,无论这个key值出现多少次,只要在最终结果输出一次就可以了。所以这里应该把每行数据作为可以key值,value值没有要求,可以设置为空。
设计思路:
按照默认的TextInputFormat格式每行文本形成一个<key,vlaue>对,key为行号,value为文本值;
在Mapper中进行处理时,将key设置为文本值(即Map输入的value值),value设置为空即可,因为此处不需要知道key值得个数等其他信息,所以此时只要比较key是否相等就可判断是否为重复的数据;
在Reducer中进行处理时,因为所有相同key值得value对都会送至一台reduce机器上调用reduce函数进行处理。在reduce函数中,我们知道reduce函数的输入是一个key值和这个key相对应的一个value列表,所以我们这里我们不管这个key值有多少个value,只要直接将key复制为输出的key值简单的输出一次即可(输出的value设置为空)。
程序代码如下:
Mapper类:
public class DeDuMap extends Mapper<Object, Text, Text, Text>{ private Text data = new Text(); public void map(Object key, Text value,Context context) throws IOException, InterruptedException{ data.set(value.toString()); context.write(data, new Text("")); } }
Reducer类:
public class DeDuReduce 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 class DeDumain { public static void main(String[] args) throws Exception{ Configuration conf = new Configuration(); String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); if (otherArgs.length != 2) { System.err.println("Usage: Dedumain <in> <out>"); System.exit(2); } Job job = new Job(conf,"de du"); job.setJarByClass(DeDumain.class); job.setMapperClass(DeDuMap.class); job.setCombinerClass(DeDuReduce.class); job.setReducerClass(DeDuReduce.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); System.exit(job.waitForCompletion(true)? 0:1); } }