为二次排序创建复合键类

laik7k3q  于 2021-05-30  发布在  Hadoop
关注(0)|答案(2)|浏览(456)

我试图创建一个 String uniqueCarrier 以及 int month 用于二次排序。谁能告诉我,同样的步骤是什么。

aoyhnmkz

aoyhnmkz1#

你的 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 partitionner会调用此方法,以便在缩减器之间分配工作。
我还会编写定制的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关于实现rawcomarator的建议,以防止每次都要解组一个对象。

kxxlusnw

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,则只需编写:

SELECT ...
FROM my_table
ORDER BY month, carrier;

上面的代码编写起来比试图弄清楚如何编写二级排序要简单得多(最终当您需要再次使用它时,如何以通用的方式进行)。mapreduce应该被认为是一个低级编程范例,并且应该只在您需要高性能优化时使用(imho),而这些优化不是从pig或hive这样的高级项目获得的。
编辑:忘了提到分组比较器,见马特的答案

相关问题