MapReduce编程——输入文件的排序

输入:A.txt

33
37
12
40

B.txt

4
16
39
5

C.txt

1
45
25

代码如下:

package com.MergeSort;

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.Partitioner;
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 MergeSort {

	/**
	 * @param args
	 * 输入多个文件,每个文件中的每行内容均为一个整数
	 * 输出到一个新的文件中,输出的数据格式为每行两个整数,第一个数字为第二个整数的排序位次,第二个整数为原待排列的整数
	 */
	//map函数读取输入中的value,将其转化成IntWritable类型,最后作为输出key
	public static class Map extends Mapper<Object, Text, IntWritable, IntWritable>{

		private static IntWritable data = new IntWritable();
		public void map(Object key, Text value, Context context) throws IOException,InterruptedException{
			String text = value.toString();
			data.set(Integer.parseInt(text));
			context.write(data, new IntWritable(1));
		}
	}

	//reduce函数将map输入的key复制到输出的value上,然后根据输入的value-list中元素的个数决定key的输出次数,定义一个全局变量line_num来代表key的位次
	public static class Reduce extends Reducer<IntWritable, IntWritable, IntWritable, IntWritable>{
		private static IntWritable line_num = new IntWritable(1);

		public void reduce(IntWritable key, Iterable<IntWritable> values, Context context) throws IOException,InterruptedException{
			for(IntWritable val : values){
				context.write(line_num, key);
				line_num = new IntWritable(line_num.get() + 1);
			}
		}
	}

	//自定义Partition函数,此函数根据输入数据的最大值和MapReduce框架中Partition的数量获取将输入数据按照大小分块的边界,然后根据输入数值和边界的关系返回对应的Partiton ID
	public static class Partition extends Partitioner<IntWritable, IntWritable>{
		public int getPartition(IntWritable key, IntWritable value, int num_Partition){
			int Maxnumber = 65223;//int型的最大数值
			int bound = Maxnumber/num_Partition+1;
			int keynumber = key.get();
			for (int i = 0; i<num_Partition; i++){
				if(keynumber<bound * (i+1) && keynumber>=bound * i){
					return i;
				}
			}
			return -1;
		}
	}

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		Configuration conf = new Configuration();
		conf.set("fs.default.name","hdfs://localhost:9000");
		String[] otherArgs = new String[]{"input","output"}; /* 直接设置输入参数 */
		if (otherArgs.length != 2) {
			System.err.println("Usage: wordcount <in> <out>");
			System.exit(2);
			}
		Job job = Job.getInstance(conf,"Merge and Sort");
		job.setJarByClass(MergeSort.class);
		job.setMapperClass(Map.class);
		job.setReducerClass(Reduce.class);
		job.setPartitionerClass(Partition.class);
		job.setOutputKeyClass(IntWritable.class);
		job.setOutputValueClass(IntWritable.class);
		FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
		FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
		System.exit(job.waitForCompletion(true) ? 0 : 1);

	}

}

在MapReduce流程中,Map的输出<Key,value>经过shuffle过程聚集成<key,value-list>后会被交给Reduce。所以从设计好的Reduce输入可以反推出Map的输出的Key应为数据,而value为任意值。继续反推,Map输出的Key为数据。而在这个实例中每个数据代表输入文件中的一行内容,所以Map阶段要完成的任务就是在采用Haodoop默认的作业输入方式之后,将value设置成Key,并直接输出(输出中的value任意)。Map中的结果经过shuffle过程之后被交给reduce。在Reduce阶段不管每个Key有多少个value,都直接将输入的Key复制为输出的Key,并输出就可以了(输出中的value被设置成空)

参考链接:https://blog.csdn.net/qq_42451251/article/details/105835325
参考链接:http://dblab.xmu.edu.cn/blog/2481-2/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值