大数据技术基础之Hadoop MapReduce 平均值计算教程

在这个教程中,我们将构建一个简单的 Hadoop MapReduce 程序,以计算一组数字的平均值。我们将详细讲解每个组件,强调关键概念和易错点,以帮助你更好地理解。

1. 项目结构

我们的项目包括以下三个类:

  • AvgMapper: 负责读取输入数据,输出每个数字及其计数。
  • AvgReducer: 负责计算总和和计数,最终输出平均值。
  • AvgDriver: 负责设置和启动 MapReduce 作业。
2. AvgMapper 类

Mapper 的主要任务是将每个输入数字映射为 key-value 对。

package com.yao.mapreduce.demo6;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

public class AvgMapper extends Mapper<LongWritable, Text, IntWritable, IntWritable> {
	# 初始化计数1
    private final static IntWritable v = new IntWritable(1);

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    	# 类型转换
        int number = Integer.parseInt(value.toString());
        # 当扫描过的数值标注1
        context.write(new IntWritable(number), v);
    }
}

重点和易错点:

  • 输入格式:确保输入数据每行都是一个整数。如果输入数据格式不正确,将导致 NumberFormatException
  • 输出类型context.write(new IntWritable(number), v); 这里我们输出 key 为数字,value 固定为 1。确认 Mapper 输出类型与 Driver 设置一致。
3. AvgReducer 类

Reducer 负责对所有输入的相同键的值进行汇总,计算总和和计数。

package com.yao.mapreduce.demo6;

import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class AvgReducer extends Reducer<IntWritable, IntWritable, Text, DoubleWritable> {
    private DoubleWritable result = new DoubleWritable();
    private int totalSum = 0;
    private int totalCount = 0;

    @Override
    protected void reduce(IntWritable key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int count = 0;
        # 循环处理key相同的value
        for (IntWritable value : values) {
        	# 出现次数进行相加
            count += value.get();
        }
        # 计算出总和
        totalSum += key.get() * count;
        totalCount += count;
    }

    @Override
    protected void cleanup(Context context) throws IOException, InterruptedException {
    	# 判断除数为零
        if (totalCount != 0) {
            double avg = (double) totalSum / totalCount;
            result.set(avg);
            # 将结果写出
            context.write(new Text("整体平均值"), result);
        }
    }
}

重点和易错点:

  • 累加逻辑totalSum += key.get() * count;totalCount += count; 确保你正确累加当前数字的总和及其出现次数。
  • 浮点数除法:在计算平均值时,务必使用 double 类型的除法,防止整数除法造成的精度损失。
  • cleanup 方法cleanup 方法在所有 reduce 完成后被调用,确保在此方法中输出最终结果。
  • 在reduce阶段避免将相同的key只处理第一个
  • 在reduce的最后将数值进行总体的求和然后计算平均
  • 注意除数的类型转换
4. AvgDriver 类

Driver 设置 MapReduce 作业的配置和运行。

package com.yao.mapreduce.demo6;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.util.Random;

public class AvgDriver {
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
    	# 为了便于测试,使用随机数命名文件,避免重复
        Random random = new Random();
        int randomInt = random.nextInt();

        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);

        job.setJarByClass(AvgDriver.class);
        job.setMapperClass(AvgMapper.class);
        job.setReducerClass(AvgReducer.class);
        #定义map阶段输出的key的类型
        job.setMapOutputKeyClass(IntWritable.class);
        #定义map阶段输出的value的类型
        job.setMapOutputValueClass(IntWritable.class);
        #定义reduce最后输出key的类型
        job.setOutputKeyClass(Text.class);
        #定义reduce最后输出value的类型
        job.setOutputValueClass(DoubleWritable.class);
        
        FileInputFormat.setInputPaths(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        boolean result = job.waitForCompletion(true);
        System.exit(result ? 0 : 1);
    }
}

重点和易错点:

  • 配置类Configuration conf = new Configuration(); 确保 Hadoop 配置正确,避免因环境问题导致的错误。
  • 输入输出路径:确保路径有效,输出路径必须不存在,否则会导致作业失败。可以在运行前手动删除旧的输出目录。
  • 类路径设置job.setJarByClass(AvgDriver.class); 确保设置 JAR 包的路径。
5. 运行程序
  1. 编译打包:确保所有类都已编译并打包成 JAR 文件,包含所有依赖。

  2. 运行作业:在 Hadoop 集群上使用以下命令运行作业:

    hadoop jar your-jar-file.jar com.yao.mapreduce.demo6.AvgDriver /input/path /output/path
    

重点和易错点:

  • 命令行参数:确保传入的输入路径和输出路径正确。如果路径错误或文件不存在,作业将无法执行。
  • 查看作业状态:可以通过 Hadoop 的 Web UI 查看作业执行状态和日志,有助于排查问题。

示例输入

1
1
2
2
1
9
9
9
9
9
9
9
9
9
9
9
9
999
999999999

示例输出

在这里插入图片描述

6. 总结

在这个教程中,我们详细介绍了如何使用 Hadoop MapReduce 计算一组数字的平均值。通过逐步分析代码,我们突出了关键逻辑和易错点,帮助你避免常见的错误。希望这能帮助你在实践中更好地应用 Hadoop 技术!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值