有时候你会遇到这样的问题:你有一个表格,给出了每个人在十二月,一月和二月的收入。
表格如下:
姓名 一月 二月 三月
楚乔 200 314 3500
宇文玥 2000 332 2300
烟熏柿子 6000 333 680
淳儿 5000 333 789
洛河 30 12 2900
现在需要知道每个人这三个月的收入平均值,那么你就需要将表格中一行代表收入的数字相加除以月数.下面请编写MR程序解决这个简单的问题。
输入只包含一个文件,它的结构如下:(数据自己做格式化)
input:
1 200 314 3500 2 2000 332 2300 3 6000 333 680 4 5000 333 789 5 30 12 2900
其中每行最前面的数字是行标
输出是一个文本文件,每一行第一个数字式行标,第二个数字是输入文件中每一行除行标外数字的平均值。
如下:
Output:
1 1338 2 1544 3 2337.67 4 2040.67 5 980.67
代码如下(由于水平有限,不保证完全正确,如果发现错误欢迎指正):
package com; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.LongWritable; 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; public class MonthTest2 { public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { Configuration config = new Configuration(); config.set("fs.defaultFS", "hdfs://192.168.0.100:9000"); config.set("yarn.resourcemanager.hostname", "192.168.0.100"); FileSystem fs = FileSystem.get(config); Job job = Job.getInstance(config); job.setJarByClass(MonthTest2.class); //设置所用到的map类 job.setMapperClass(myMapper.class); job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(Text.class); //设置所用到的reduce类 job.setReducerClass(myReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); //设置输入输出地址 FileInputFormat.addInputPath(job, new Path("/input/month.txt")); Path path = new Path("/output1/"); //判断目录文件是否存在,存在的话,删除 if(fs.exists(path)){ fs.delete(path, true); } //指定结果文件的输出地址 FileOutputFormat.setOutputPath(job,path); //启动处理任务job boolean completion = job.waitForCompletion(true); if(completion){ System.out.println("Job Success!"); } } public static class myMapper extends Mapper<LongWritable,Text, Text, Text>{ @Override protected void map(LongWritable key, Text value,Context context) throws IOException, InterruptedException { String values=value.toString(); String words[]=values.split(" "); //1 200 314 3500 float avg=(Float.parseFloat(words[1])+Float.parseFloat(words[2])+Float.parseFloat(words[3]))/3; String aaa=String.format("%.2f", avg);//保留两位小数 context.write(new Text(words[0]), new Text(aaa)); } } public static class myReducer extends Reducer< Text, Text, Text, Text>{ @Override protected void reduce(Text key, Iterable<Text> values,Context context) throws IOException, InterruptedException { for (Text value : values) { if(value.toString().endsWith(".00")){ // 判断出以.00结尾的数字 String[] aa = value.toString().split(".00");//1338.00--->aa[0]=1338 context.write(key,new Text(aa[0])); }else{ context.write(key, value); } } } } }
注意:主要难点在于整数不要求保留两位小数且不要小数点,float类型的话要求保留两位小数
如果您认为这篇文章还不错或者有所收获,您可以通过右边的“打赏”功能 打赏我一杯咖啡【物质支持】,也可以点击下方的【好文要顶】按钮【精神支持】,因为这两种支持都是使我继续写作、分享的最大动力!