0

我正在尝试为二级排序创建一个复合键String uniqueCarrier类。int month谁能告诉我,相同的步骤是什么。

4

2 回答 2

0

您的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 monthText uniqueCarrier)。这使我可以直接调用它们writereadFields也可以使用它们的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 的建议,以防止每次都必须解组到对象。

于 2015-03-18T03:31:05.840 回答
0

看起来你有一个平等问题,因为你没有在 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 等更高级别的项目中获得。

编辑:忘记提及分组比较器,请参阅马特的回答

于 2015-03-18T03:12:00.690 回答