我有以下设置:映射器输出密钥类型为K1
且值类型为V1
,K1
为WritableComparable
的记录。因此,组合器获得K1
和Iterable<V1>
作为其输入。然后它进行聚合并输出一个K1, V1
记录。 reducer从组合器获取输入,再次为K1, Iterable<V1>
。据我所知,在Reduce阶段,每个人K1, Iterable<V1>
必须只有一个K1
对。然后减速器只输出一个K2, V2
。 K2
再次WritableComparable
。
我现在的问题是:我的输出文件中有多个K2, V2
,即使在同一个文件中也是如此!我的关键类的比较方法是正确的,我仔细检查了它。这里出了什么问题?我是否还必须实现equals和hashCode?我认为通过比较和检查比较结果是否为0来执行相等。
还是有其他我遗忘的东西吗?
以下是关键实施:
可写密钥继承自:
package somepackage;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.Writable;
public class SomeWritable implements Writable {
private String _string1;
private String _string2;
public SomeWritable() {
super();
}
public String getString1() {
return _string1;
}
public void setString1(final String string1) {
_string1 = string1;
}
public String getString2() {
return _string2;
}
public void setString2(final String string2) {
_string2 = string2;
}
@Override
public void write(final DataOutput out) throws IOException {
out.writeUTF(_string1);
out.writeUTF(_string2);
}
@Override
public void readFields(final DataInput in) throws IOException {
_string1 = in.readUTF();
_string2 = in.readUTF();
}
}
我使用的密钥:
package somepackage;
import static org.apache.commons.lang.ObjectUtils.compare;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.WritableComparable;
public class SomeKey extends SomeWritable implements
WritableComparable<SomeKey> {
private String _someOtherString;
public String getSomeOtherString() {
return _someOtherString;
}
public void setSomeOtherString(final String someOtherString) {
_someOtherString = someOtherString;
}
@Override
public void write(final DataOutput out) throws IOException {
super.write(out);
out.writeUTF(_someOtherString);
}
@Override
public void readFields(final DataInput in) throws IOException {
super.readFields(in);
_someOtherString = in.readUTF();
}
@Override
public int compareTo(final SomeKey o) {
if (o == null) {
return 1;
}
if (o == this) {
return 0;
}
final int c1 = compare(_someOtherString, o._someOtherString);
if (c1 != 0) {
return c1;
}
final int c2 = compare(getString1(), o.getString1());
if (c2 != 0) {
return c2;
}
return compare(getString2(), o.getString2());
}
}
答案 0 :(得分:0)
我解决了这个问题:为了确保相同的密钥始终分配给同一个reducer,密钥的hashCode()
必须基于密钥中的当前值来实现。即使它们是可变的。有了这个,一切正常。
必须非常小心,不要在集合中使用这些类型或在地图等中使用键。