我是靠谱客的博主 务实银耳汤,最近开发中收集的这篇文章主要介绍MapReduce中自定义bean对象并实现序列化接口,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

实现bean对象序列化步骤有如下7步。
(1)实现Writable接口
(2)反序列化时,需要反射调用无参构造器,所以必须有无参构造器
(3)重写序列化方法
(4)重写反序列化方法
(5)注意反序列化的顺序和序列化的顺序完全一致
(6)要想把结果显示在文件中,需要重写toString()
(7)如果需要将自定义的bean放在key中传输,则还需要实现Comparable接口,因为MapReduce框中的Shuffle过程要求对key必须能排序
下面我们来看一个具体的案例
需求:统计每一个手机号耗费的总上行流量、下行流量、总流量
(1)、输入数据
在这里插入图片描述
(2)、输入数据格式
1 13560436666 120.196.100.99 1116 954 200
id 手机号码 网络ip 上行流量 下行流量 网络状态码
(3)期望输出数据格式
13560436666 1116 954 2070
手机号码 上行流量 下行流量 总流量
(4)、分析:
由于手机号是不变的,所以我们可以将手机号作为key,上行流量与下行流量包装为一个对象
(5)、代码实现
FlowBean:

package com.atguigu.mapreduce;
import org.apache.hadoop.io.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
 * @author yqw
 * @since 2020-07-28 9:14
 */
// 1 实现writable接口
public class FlowBean implements Writable {
    private long upFlow;    // 上行流量
    private long downFlow;  // 下行流量
    private long sumFlow;   // 总流量
    //2  反序列化时,需要反射调用空参构造函数,所以必须有
    public FlowBean() {
        super();
    }
    public void setDownFlow(long downFlow) {
        this.downFlow = downFlow;
    }
    public void setSumFlow(long sumFlow) {
        this.sumFlow = sumFlow;
    }
    public long getDownFlow() {
        return downFlow;
    }
    public long getSumFlow() {
        return sumFlow;
    }
    public FlowBean(long upFlow, long downFlow) {
        super();
        this.upFlow = upFlow;
        this.downFlow = downFlow;
        this.sumFlow = upFlow + downFlow;
    }
    
    public void setUpFlow(long upFlow) {
        this.upFlow = upFlow;
    }
    public long getUpFlow() {
        return upFlow;
    }
    // 3 写序列化方法
    @Override
    public void write(DataOutput dataOutput) throws IOException {
        dataOutput.writeLong(upFlow);
        dataOutput.writeLong(downFlow);
        dataOutput.writeLong(sumFlow);
    }
    // 4 反序列化方法
    // 5 反序列化方法读顺序必须和写序列化方法的写顺序必须一致
    @Override
    public void readFields(DataInput dataInput) throws IOException {
        this.upFlow=dataInput.readLong();
        this.downFlow=dataInput.readLong();
        this.sumFlow=dataInput.readLong();
    }
    // 6 编写toString方法,方便后续打印到文本
    @Override
    public String toString() {
        return upFlow + "t" + downFlow + "t" + sumFlow;
    }
}

Mapper:

package com.atguigu.mapreduce;
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 org.apache.hadoop.yarn.webapp.hamlet.HamletSpec;
import java.io.IOException;
/**
 * @author yqw
 * @since 2020-07-28 9:15
 */
public class FlowCountMapper extends Mapper<LongWritable, Text,Text, FlowBean> {
    private FlowBean flowBean ;
    private Text k = new Text();
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // 切分数据
        String[] words = value.toString().split("t");
        // 取出手机号码
        k.set(words[1]);
        // 取出上行流量
        long upFlow = Long.parseLong(words[3]);
        // 取出下行流量
        long downFlow = Long.parseLong(words[4]);
        // 封装为FlowBean对象
        flowBean=new FlowBean(upFlow,downFlow);
        // 写出
        context.write(k,flowBean);
    }
}

Reducer:

package com.atguigu.mapreduce;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
 * @author yqw
 * @since 2020-07-28 9:15
 */
public class FlowCountReducer extends Reducer<Text, FlowBean, Text, FlowBean> {
    private FlowBean flowBean ;
    @Override
    protected void reduce(Text key, Iterable<FlowBean> values, Context context) throws IOException, InterruptedException {
        Long sumUpFlow = 0L;
        Long sumDownFlow = 0L;
        // 遍历FlowBean,将上行流量与下行流量分别叠加
        for (FlowBean value : values) {
            sumUpFlow += value.getUpFlow();
            sumDownFlow += value.getDownFlow();
        }
        // 封装FlowBean
        flowBean=new FlowBean(sumUpFlow,sumDownFlow);
        // 写出
        context.write(key,flowBean);
    }
}

Driver:

package com.atguigu.mapreduce;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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;
/**
 * @author yqw
 * @since 2020-07-28 9:15
 */
public class FlowCountDriver {
    public static void main(String[] args) throws Exception {
        // 1 获取配置信息以及封装任务
        Configuration conf = new Configuration();
        // 每个MapReduce任务都被初始化为一个Job,它分为两个阶段,map和reduce阶段
        Job job = Job.getInstance(conf);
        // 2 设置jar加载路径
        job.setJarByClass(FlowCountDriver.class);
        // 3 设置Mapper和Reducer类
        job.setMapperClass(FlowCountMapper.class);
        job.setReducerClass(FlowCountReducer.class);
        // 4 设置map输出
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(FlowBean.class);
        // 5 设置最终输出kv类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(FlowBean.class);
        // 6 设置输入和输出路径
        FileInputFormat.setInputPaths(job,new Path(args[0]) );
        FileOutputFormat.setOutputPath(job,new Path(args[1]));
        // 7 提交
        boolean result = job.waitForCompletion(true);
        // 退出
        System.exit(result ? 0 : 1);
    }
}

(6)、结果
在这里插入图片描述

最后

以上就是务实银耳汤为你收集整理的MapReduce中自定义bean对象并实现序列化接口的全部内容,希望文章能够帮你解决MapReduce中自定义bean对象并实现序列化接口所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部