我正在尝试为二级排序创建一个复合键String uniqueCarrier
类。int month
谁能告诉我,相同的步骤是什么。
2 回答
您的compareTo()
实现不正确。您需要先排序uniqueCarrier
,然后再month
打破平等:
@Override
public int compareTo(CompositeKey other) {
if (this.getUniqueCarrier().equals(other.getUniqueCarrier())) {
return this.getMonth().compareTo(other.getMonth());
} else {
return this.getUniqueCarrier().compareTo(other.getUniqueCarrier());
}
}
不过有一个建议:如果可能,我通常选择将我的属性直接实现为可写类型(例如,IntWriteable month
和Text uniqueCarrier
)。这使我可以直接调用它们write
,readFields
也可以使用它们的compareTo
. 少写代码总是好的……
说到更少的代码,您不必为复合键调用父构造函数。
现在剩下要做的事情:
我的猜测是你仍然缺少一个hashCode()
方法,在这种情况下,它应该只返回你想要分组的属性的哈希值uniqueCarrier
。默认的 Hadoop 分区程序调用此方法来跨 reducer 分配工作。
我还将编写自定义 GroupingComparator 和 SortingComparator 以确保分组仅发生在 上uniqueCarrier
,并且排序的行为根据CompositeKey
compareTo()
:
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);
}
}
然后,告诉您的驱动程序使用这两个:
job.setSortComparatorClass(CompositeSortingComparator.class);
job.setGroupingComparatorClass(CompositeGroupingComparator.class);
编辑:如果您想进一步优化,另请参阅Pradeep 的实现 RawComparator 的建议,以防止每次都必须解组到对象。
看起来你有一个平等问题,因为你没有在 compareTo 方法中使用 uniqueCarrier 。您需要在 compareTo 和 equals 方法中使用 uniqueCarrier(也定义一个 equals 方法)。来自java lang 参考
当且仅当 e1.compareTo(e2) == 0 对于类 C 的每个 e1 和 e2 具有与 e1.equals(e2) 相同的布尔值时,类 C 的自然排序被称为与 equals 一致。注意null 不是任何类的实例,即使 e.equals(null) 返回 false,e.compareTo(null) 也应该抛出 NullPointerException。
您还可以实现RawComparator以便您可以在不反序列化的情况下比较它们以获得更快的性能。
但是,我建议(就像我一直做的那样)不要自己编写二级排序之类的东西。这些已在 Pig 和 Hive 等项目中实施(以及许多其他优化)。例如,如果您使用 Hive,您只需编写:
SELECT ...
FROM my_table
ORDER BY month, carrier;
上面写起来比试图弄清楚如何编写二级排序要简单得多(最终当您需要再次使用它时,如何以通用方式进行操作)。MapReduce 应该被认为是一种低级编程范式,并且应该只在您需要高性能优化时使用(恕我直言),而您无法从 Pig 或 Hive 等更高级别的项目中获得。
编辑:忘记提及分组比较器,请参阅马特的回答