一、第一个MapReduce应用程序
1.实现继承Mapper的类:WordCountMapper
// 实现Map程序 public static class WordCountMapper extends Mapper<LongWritable,Text,Text,LongWritable>{ public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { //将传进来的字符串进行分割 System.out.println("Usage:3.1"); String strs = value.toString(); System.out.println("Usage:3.1.1"); String[] str = strs.split(" "); System.out.println("Usage:3.2"); //将分割的字符串进行赋值 for(String key2 : str ){ context.write(new Text(key2),new LongWritable(1)); } System.out.println("Usage:3.3"); } }
2.实现继承Reducer的类:WordCountReducer
// 实现Reduce程序 public static class WordCountReduce extends Reducer<Text,LongWritable,Text,LongWritable>{ public void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException { //定义一个求和值默认为0 long sum = 0; // 将相同key键的值进行累加 for (LongWritable i : values){ sum+=i.get(); } context.write(key,new LongWritable(sum)); } }
3.主程序中创建一个job去执行mapreducer程序
public static void main(String[] args) throws Exception{ Configuration conf = new Configuration(); Job job = new Job(conf); //设置程序入口 job.setJarByClass(WordCountDemo.class); // 设置文件输入数据 FileInputFormat.setInputPaths(job,new Path(args[0])); //设置文件输出数据 FileOutputFormat.setOutputPath(job,new Path(args[1])); // 设置Map job.setMapperClass(WordCountMapper.class); job.setMapOutputKeyClass(Text.class); //注意输出的key value值,否则报异常 job.setOutputValueClass(LongWritable.class); // 设置Reduce job.setReducerClass(WordCountReduce.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(LongWritable.class); // 启动 job.waitForCompletion(true); }
二、Hadoop的序列化
序列化:是指把结构化的对象转化成字节流
逆序列化:是序列化的逆序过程,是将字节流转化成结构化对象
* 编写Hadoop序列化程序
1.创建一个Emp对象并实现序列化接口Writable
2.实现Writable的两个方法:write()、readFields()方法
3.实现Emp属性的getter/setter方法以及toString()
4.创建一个EmpMain类来实现序列化的MapReduce程序
5.创建一个Mapper<LongWritable,Text,LongWritable,Emp>类
// 分词 String[] vals = value.toString().split(","); //设置属性 Emp emp = new Emp(); emp.setEmpid(Integer.parseInt(vals[0]));//员工号 emp.setName(vals[1]); emp.setJob(vals[2]); try { emp.setMgr(Integer.parseInt(vals[3])); } catch (NumberFormatException e) { emp.setMgr(0); } emp.setHiredate(vals[4]); emp.setPrice(Integer.parseInt(vals[5])); try { emp.setJiangjin(Integer.parseInt(vals[6])); } catch (NumberFormatException e) { emp.setJiangjin(0); } // 输出 context.write(new LongWritable(emp.getEmpid()),emp);6.在main方法中配置信息,导出jar包在hadoop上运行
三、实现MapReduce排序
注意:实现排序过程中是通过key来进行排序,而在value中是不进行排序
1.Emp对象实现WritableComparable<Emp>接口的方法:comparaTo(),按规则薪资升序
2.在实现MapReduce的Mapper过程中,需将Emp调整为key2输出,这样才能排序
四、实现MapReduce分区
MapReduce有一个默认的分区规则:只会产生一个分区
1.在创建分区程序过程中需要创建继承Partitioner的类并实现getPartition()方法
2.通过reducer的数目进行分区,编写分区规则
// 建立分区 public static class EmpPartition extends Partitioner<LongWritable,Emp>{ @Override public int getPartition(LongWritable key, Emp emp, int num) { // num为Reducer的数目 int deptno = emp.getDeptno(); if (deptno == 10 ){ return 1 % num; }else if (deptno == 20 ){ return 2 % num; }else{ return 3 % num; } } }
3.在main主函数中添加分区规则
//设置分区Partitioner job.setPartitionerClass(EmpPartition.class); // 设置reducer数目大小 job.setNumReduceTasks(3);4.reducer数目的大小决定需要将数据分成多个区
五、MapReduce的Combiner
Combiner是一个特殊的Reducer,它会在Mapper端对数据进行一次合并,减少IO访问,输出到Reducer的数据量减少,提高效率。但Combiner在求平均值等一些特殊情况不能使用,所以在使用Combiner过程中需慎重考虑。
通过在主程序设置 job.setCombinerClass(EmpReduce.class) 即可
六、MapReduce的Shuffle
参考:https://blog.csdn.net/u012151684/article/details/72589302