[英]Strange behavior on Hadoop's reducer
我有一个名为Pair
的简单类,该类实现org.apache.hadoop.io.Writable
。 它包含两个字段,并在MapReduce流程中用作值。
对于每个键,我想找到对值最大的对,其中一个对是字段(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);
第二个代码为每个键生成在输入文件中与其关联的最后一个值,而不是最大值。
这种明显奇怪的行为是否有原因?
您有这个问题,因为化简器正在重用对象,因此其对值的迭代器始终将同一个对象传递给您。 因此这段代码:
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
,因此代码稍作更改即可直接访问公共类变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.