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:柘月十七

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