public class CompositeGroupingComparator extends WritableComparator {
public CompositeGroupingComparator() {
super(CompositeKey.class, true);
}
@Override
public int compare(WritableComparable a, WritableComparable b) {
CompositeKey first = (CompositeKey) a;
CompositeKey second = (CompositeKey) b;
return first.getUniqueCarrier().compareTo(second.getUniqueCarrier());
}
}
public class CompositeSortingComparator extends WritableComparator {
public CompositeSortingComparator()
{
super (CompositeKey.class, true);
}
@Override
public int compare (WritableComparable a, WritableComparable b){
CompositeKey first = (CompositeKey) a;
CompositeKey second = (CompositeKey) b;
return first.compareTo(second);
}
}
2条答案
按热度按时间aoyhnmkz1#
你的
compareTo()
执行不正确。你得先分类uniqueCarrier
,然后继续month
打破平等:不过有一个建议:如果可能的话,我通常选择直接将属性实现为可写类型(例如,
IntWriteable month
以及Text uniqueCarrier
). 这样我就可以打电话了write
以及readFields
直接在他们身上,也使用他们的compareTo
. 少写代码总是好的。。。说到更少的代码,您不必为复合键调用父构造函数。
现在我们要做的是:
我猜你还缺一个
hashCode()
方法,在本例中,该方法应仅返回要分组的属性的哈希值uniqueCarrier
. 默认情况下,hadoop partitionner会调用此方法,以便在缩减器之间分配工作。我还会编写定制的groupingcomparator和sortingcomparator,以确保分组只在
uniqueCarrier
,排序的行为根据CompositeKey
compareTo()
:然后,告诉你的司机使用这两种方法:
编辑:如果您想进一步优化,请参阅pradeep关于实现rawcomarator的建议,以防止每次都要解组一个对象。
kxxlusnw2#
由于在compareto方法中未使用uniquecarrier,因此似乎存在相等问题。您需要在compareto和equals方法中使用uniquecarrier(还需要定义equals方法)。来自java语言参考
当且仅当c类的每一个e1和e2的e1.compareto(e2)==0具有与e1.equals(e2)相同的布尔值时,c类的自然序才与equals一致。注意,null不是任何类的示例,即使e.equals(null)返回false,e.compareto(null)也应该抛出nullpointerexception。
您还可以实现rawcomparator,这样就可以比较它们,而无需反序列化以获得更快的性能。
不过,我建议(就像我一直做的那样)不要自己写二次排序之类的东西。这些已经在pig和hive等项目中实现(以及其他许多优化)。e、 g.如果您使用的是hive,则只需编写:
上面的代码编写起来比试图弄清楚如何编写二级排序要简单得多(最终当您需要再次使用它时,如何以通用的方式进行)。mapreduce应该被认为是一个低级编程范例,并且应该只在您需要高性能优化时使用(imho),而这些优化不是从pig或hive这样的高级项目获得的。
编辑:忘了提到分组比较器,见马特的答案