【问题标题】:Strange behavior on Hadoop's reducerHadoop减速器的奇怪行为
【发布时间】:2018-03-09 03:01:22
【问题描述】:

我有一个名为Pair 的简单类,它实现了org.apache.hadoop.io.Writable。它包含两个字段,在 MapReduce 过程中用作 Value。

对于每个键,我想找到 Pair 的一个字段(preco)中值最大的对。在 reducer 中,下面的代码会产生预期的结果:

float max = 0;
String country = "";
for (Pair p : values){
    if (p.getPreco().get() > max)
    {
        max = p.getPreco().get();
        country = p.getPais().toString();
    }
}
context.write(key, new Pair(new FloatWritable(max), new Text(country)));

另一方面,下面的代码没有:

Pair max = new Pair();
for (Pair p : values)
    if (p.getPreco().get() > max.getPreco().get())
        max = p;

context.write(key, max);

第二个代码为每个键生成输入文件中与之关联的最后一个值,而不是最大值。

这种明显奇怪的行为是否有原因?

【问题讨论】:

    标签: java hadoop mapreduce


    【解决方案1】:

    你有这个问题是因为reducer 重用了对象,所以它对值的迭代器总是向你传递同一个对象。因此这段代码:

    max = p;

    将始终引用p 的当前值。您需要将数据复制到 max 以使其正常工作并且不引用该对象。这就是为什么您的代码的第一个版本可以正常工作的原因。

    通常在 Hadoop 中,我会在自定义可写对象上实现 .set() 方法,这是您将看到的常见模式。所以你的Pair 类可能看起来有点像(它缺少接口方法等):

    public class Pair implements Writable {
    
        public FloatWritable max = new FloatWritable();
        public Text country = new Text();
    
        public void set(Pair p) {
            this.max.set(p.max.get());
            this.country.set(p.country);
        }
    }
    

    您可以将代码更改为:

    Pair max = new Pair();
    for (Pair p : values) {
        if (p.max().get() > max.max.get()) {
            max.set(p);
        }
    }
    context.write(key, max);
    

    我还没有在Pair中创建getters,所以代码稍作改动,直接访问公共类变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-06
      • 2021-01-29
      • 1970-01-01
      • 1970-01-01
      • 2016-07-02
      • 2013-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多