WordCount大变身做一些简单的数据处理应用案列


————————————————————————————————————————

前言

WordCount算是我们学习hadoop的第一分布式计算程序了,那么把它大致的过程都啃透了将对学习后面的相关知识很有必要。WordCount1.0 代码详解,下面将分析一个2.0版本的“WordCount”的实现任务,相信自己,加油!

任务描述

主要梗概:对如下的样本数据进行编程实现数据的清洗和排序;

Zhangsan 90 83 88
Lisi 83 76 73

Wangwu 84 81 77
Zhaoliu 77 67

Chentian 78 91 82
Liutao 83

具体要求如下:

  1. 将文件中的空行清洗掉;
  2. 将文件中的不符合规则的内容清洗掉(每行内容一定要有四个字段);
  3. 对清洗后的数据进行统计,计算每个同学的总成绩和平均分,最终输出的形式为: 姓名 总成绩 平均分
  4. 对清洗后的数据进行排序处理,按照学生的总成绩由小到大进行排序,输出的形式仍然为: 姓名 总成绩 平均分

任务要求就这么多,你是否已经有思路了?不管怎么样,不着急往下看分析过程,先捋捋思路或者自己试着完成它再往下看看,加油相信自己!

任务分析

这里就当你已经对WordCount程序了解了个大概了,如果还没有点这里。既然上面的任务分点了,那么接下来也按点分析:

  1. 要把空行清理了,那么把输出字符是“\n”的筛选掉就可以了。
  2. 要把不合理的内容清洗掉,换个思路来,我们把合理的内容留下来就可以了;对每条数据截取字段后放到数组,那么数组的长度是4,长度不是4的都筛选掉。
  3. 对数组元素进行计算并输出,难点来了(画起来喔,要考,嘻嘻嘻)“输出三个字段”,大致实现过程:合并。没错,就是二合一,这样就可以看作两个了。
  4. 重点又来了,记得圈起来要考的呢,嘻嘻嘻!那就是排序了,难不难?相信自己!排序是这样的,实在太重要了,所以“借一步说”,往下看:

MapReduce默认排序规则

它是按照key值进行排序的,如果key为封装的int为IntWritable类型,那么MapReduce按照数字大小对key排序;
如果Key为封装String的Text类型,那么MapReduce将按照数据字典顺序对字符排序。

代码实现

具体代码如下啦
另外附上程序执行过程的一些重要注意事项,点这里

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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 org.apache.hadoop.util.GenericOptionsParser;


public class Score {
	public static class AverageMap extends Mapper<Object,Text,IntWritable,Text>{
		public void map(Object key,Text value,Context context) throws IOException,InterruptedException{
			String st= value.toString();
			//清洗空行
			if(st == "\n") {
				return;
			}
			String[] score = st.split(" ");
			//清洗不合理数据
			if(score.length != 4) {
				return;
			}
			//数据统计,求和以及求均值
			int Chinese = Integer.valueOf(score[1]);
			int Math = Integer.valueOf(score[2]);
			int English = Integer.valueOf(score[3]);
			int total = Chinese+Math+English;
			int averageScore = total/3;
			//因为需要按总分进行排序,所以将总分total以key字段输出,名字和平均分以Text类型value输出(系统默认按照key(IntWritable类型)字段以小到大进行排序)
			context.write(new IntWritable(total),new Text(score[0]+"   "+averageScore));   //“   ”  包含三个空格
		}
	}
	/*
	 * 到这里的map函数输出内容如下:
	 *  <232,lisi 77>
	 *  <242,wangwu 80>
	 *  <251,shentian 83>
	 *  <261,zhangsan 87>
	 */
	public static class AverageReduce extends Reducer<IntWritable,Text,Text,Text>{
		public void reduce(IntWritable key,Iterable<Text> values,Context context) throws IOException,InterruptedException{
			//将values遍历出来,对(总分,姓名,平均分)字段顺序进行重置(姓名,总分,平均分)
			for(Text t : values) {
				String[] tt = t.toString().split("   ");
				//字段重置,将key字段(总分)设为字符串类型,然后和平均分进行合并为Text输出
				String total = String.valueOf(key.get());
				//这里的key字段设为Text类型,value也是
				context.write(new Text(tt[0]),new Text(total+"   "+tt[1]));   //“   ”  包含三个空格
			}
		}
	}
	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: wordcount <in> <out>"); 
			System.exit(2); 
		} 
		Job job = new Job(conf, "AverageScore"); 
		job.setJarByClass(Score.class); 
		job.setMapperClass(AverageMap.class); 
		//job.setCombinerClass(IntSumReducer.class); 
		job.setReducerClass(AverageReduce.class); 
		//map函数于reduce函数中的输出的类型不一致,需要指定map的输出类型,否则会出现异常(这里也是与wordcount不一样的地方)
		job.setMapOutputKeyClass(IntWritable.class);
		job.setMapOutputValueClass(Text.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); 
	} 
}

任务最终效果

程序执行结果最终如下:
结果
若有不足之处望留言!

——————END———————
Programmer:柘月十七

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章