hadoop关于reduce方法里面迭代value问题

reducejoin  案例

其中需要在reduce方法里面遍历 value  并保存在一个集合里面

public class ReduceJoinReducer extends Reducer<IntWritable,OrderDetailBean,OrderDetailBean, NullWritable> {
    @Override
    protected void reduce(IntWritable key, Iterable<OrderDetailBean> values, Context context) throws IOException, InterruptedException {

        List<OrderDetailBean> orders = new ArrayList<>();
        String pname =null;
        OrderDetailBean detailBean = new OrderDetailBean();
        for (OrderDetailBean value : values) {

            if("order".equals(value.getTable())){
                try {
                    //为什么不直接把value add到orders集合里面
                    //直接添加会造成集合里存了都是一样的值,为最后一次添加的数据
                    BeanUtils.copyProperties(detailBean,value);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                orders.add(detailBean);
            }
            if("pd".equals(value.getTable())){
                pname = value.getPname();
            }
        }

        for (OrderDetailBean order : orders) {
            order.setPname(pname);
            context.write(order,NullWritable.get());
        }
    }
}

里面使用了BeanUtils  来copy属性到一个临时对象里面,再添加到集合中;

为什么不直接添加  order.add(value)  中呢。

如果这样最后集合里面的值都是一样的,这个value只是个引用,地址值是不变的,但是里面的值是每次迭代变化的。

造成最后保存的都是最后一次的value的值(整个list)

 

这种遍历其实调用的就是

values.next()方法

public boolean nextKey() throws IOException,InterruptedException {
    while (hasMore && nextKeyIsSame) {
      nextKeyValue();
    }
    if (hasMore) {
      if (inputKeyCounter != null) {
        inputKeyCounter.increment(1);
      }
      return nextKeyValue();
    } else {
      return false;
    }
  }

调用了  nextKeyValue()  方法

 private RawKeyValueIterator input;
 private KEYIN key;                   
 private VALUEIN value; 

public boolean nextKeyValue() throws IOException, InterruptedException {
    if (!hasMore) {
      key = null;
      value = null;
      return false;
    }
    firstValue = !nextKeyIsSame;
    DataInputBuffer nextKey = input.getKey();
    currentRawKey.set(nextKey.getData(), nextKey.getPosition(), 
                      nextKey.getLength() - nextKey.getPosition());
    buffer.reset(currentRawKey.getBytes(), 0, currentRawKey.getLength());
    key = keyDeserializer.deserialize(key);
   //input    是 private RawKeyValueIterator input;可以获取kv信息的迭代器
    DataInputBuffer nextVal = input.getValue();
    //处理获取的value
    buffer.reset(nextVal.getData(), nextVal.getPosition(), nextVal.getLength()
        - nextVal.getPosition());
//
    value = valueDeserializer.deserialize(value);

    。。。。。
    inputValueCounter.increment(1);
    return true;
  }

reset方法

public void reset(byte[] input, int start, int length) {
      this.buf = input;
      this.count = start+length;
      this.mark = start;
      this.pos = start;
    }
deserialize(Writable w)

多次循环value的地址值不变     private VALUEIN value;   这个对象的地址值是没有变化的,变化的是它里面的属性;

这就是为什么直接添加到集合里面存起来会造成整个集合里保存的都是最后一次的值了。

这又个帖子写的很好

关于 hadoop reduce 阶段遍历 Iterable 的 2 个“坑”

https://my.oschina.net/leejun2005/blog/131744#comments

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值