数据去重
"数据去重"主要是为了掌握和利用并行化思想来对数据进行有意义的筛选。统计大数据集上的数据种类个数、从网站日志中计算访问地等这些看似庞杂的任务都会涉及数据去重。下面就进入这个实例的MapReduce程序设计。
思想
对于数据去重问题,每个元素出现了多少次是不重要,因为不需要多次的进行判断是否已经存在这个元素,我只要确定每个元素只要出现过,并且最后能够显示出来就可以。那么通过map阶段后的shuffle,我们就可以把相同key的元素归并,也就是说在完成归并的同时,就实现了去重。最终reduce输出的就是具有唯一性的去重的元素集合。
所以,想要以什么元素去重,就让这个元素去作为key
举例:
始终站 日期
北京-天津 2019-09-03
北京-天津 2019-09-03 北京-天津 2019-09-03
北京-烟台 2019-09-03 北京-烟台 2019-09-03
北京-哈尔滨 2019-09-03 ===》 北京-哈尔滨 2019-09-03
北京-成都 2019-09-03 北京-成都 2019-09-03
北京-成都 2019-09-03 北京-三亚 2019-09-03
北京-三亚 2019-09-03
本例的目的,是按照 始终站和日期,两个元素来去重的。所以将始终站和日期同时作为key
代码思路
map阶段,将每行读入的信息,整体作为key,放入key-value中 ===》 <"北京-天津 2019-09-03",NULL>
reduce阶段,将map阶段shuffle完的数据,进行原样输出即可
代码
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
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.output.FileOutputFormat;
import java.io.IOException;
public class Quchong {
public static class MyMapper extends Mapper<Object, Text, Text, NullWritable>{
public Text k = new Text();
@Override
protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
String row = value.toString();
k.set(row);
context.write(k,NullWritable.get());
}
}
public static class MyReducer extends Reducer<Text, NullWritable, Text, NullWritable>{
@Override
protected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
context.write(key,NullWritable.get());
}
}
public static void main(String[] args) throws IOException {
try {
//获得配置
//Configuration conf = HdfsUtils.getConf();
//新建作业
Job job = Job.getInstance(new Configuration(),"quchong");
//设置主类
job.setJarByClass(Quchong.class);
//设置map端
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(NullWritable.class);
//设置reduce端
job.setReducerClass(MyReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class);
//设置job输入输出路径
FileInputFormat.addInputPath(job,new Path("/input/quchong/data.txt"));
FileOutputFormat.setOutputPath(job,new Path("/output/mr/quchong/test1/"));
//提交作业
int success = job.waitForCompletion(true) ? 0 : 1;
//退出
System.exit(success);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
↓