在编写MapReduce 代码时,有时候一个key需要一次性传输多个value值
例如这个案例:
现在有一堆关于手机号的数据,需要从中获取每个手机号对应的上行流量,下行流量,以及总流量(总流量=上行流量+下行流量)
(其实这个案例不用自定义Bean对象也能解决,但还是觉得,自定义Bean对象早晚会用到,所以想把看视频学到的东西总结一下)
//这里把手机号为Key,其他(上行,下行,总流量)为value,因为value不只是一个参数,所以需要自定义一个Bean对象,用来传value
下面是具体代码:(从上到下是连着的完整的代码)
//1. 自定义Bean对象 ,需要实现writable 接口
public class FlowBean implements Writable{
//定义属性
private long upFlow ; //上行流量
private long downFlow; //下行流量
private long sumFlow; //总流量
//空参构造(Alt+shift+s), 为了后续反射用
public FlowBean(){
super();
}
//有参构造(Alt+shift+s), 为了方便后期使用
public FlowBean(long upFlow,long downFlow){
super();
this.upFlow=upFlow;
this.downFlow=downFlow;
sumFlow=upFlow+downFlow;
}
//重写Writable接口的 write 方法 和 readFields 方法(会自动提示的)
//序列化方法
public void write(DataOutput out) throws IOException{
//序列化的顺序必须和反序列化的顺序保持一致
out.writeLong(upFlow);
out.writeLong(downFlow); //序列化就是为了读取数据用来传输,所以out
out.writeLong(sumFlow);
}
//反序列化方法
public void readFields(DataInput in) throws IOException{
//序列化的顺序必须和反序列化的顺序保持一致
upFlow=in.readLong();
downFlow=in.readLong(); //反序列化就是为了,写入传输过来的数据,所以in
sumFlow=in.readLong();
}
//重写toString(Alt+shift+s)
public String toString(){
//按照要求,要返回的是上行,下行,总的流量和
return upFlow+"\t"+downFlow+"\t"+sumFlow;
}
//get,set 方法(Alt+shift+s)
public long getUpFlow(){
return upFlow;
}
public void setUpFlow(long upFlow){
this.upFlow=upFlow;
}
public long getDownFlow(){
return downFlow;
}
public void setDownFlow(long upFlow){
this.downFlow=downFlow;
}
public long getSumFlow(){
return sumFlow;
}
public void setSumFlow(long sumFlow){
this.sumFlow=sumFlow;
}
}
这个地方在reducer代码部分又补了一个求和的方法,其实我觉得这个根本没必要,因为直接传给有参方法,里面就有求和:
public void set(long upFlow2,long downFlow2){
upFlow=upFlow2;
downFlow=downFlow2;
sumFlow=upFlow2+downFlow2;
}
该案例对应的Mapper阶段的代码:(Bean对象的具体使用)
Mapper阶段的代码,Bean对象的具体使用
Reducer阶段的代码