在Apache Spark(Java)中按多个值对JavaRDD元组进行排序

时间:2017-06-18 23:44:29

标签: java sorting apache-spark rdd

我很兴奋,需要用Java解决这个问题,只需使用RDD API。

我有一个JavaRDD元组,有四个值:

    JavaRDD<Tuple4 <Integer, Double, Long, Integer>> revenue = ...;

我想按Double值按降序对元组进行排序。

如果两个双打具有相同的值,我想按Long值按升序对它们进行排序。

例如:

    (7, 4.3, 5, 9)
    (1, 5.1, 7, 10)
    (8, 1.2, 4, 7)
    (1, 4.3, 4, 2)
    (3, 4.3, 8, 5)

分类为:

    (1, 5.1, 7, 10)
    (1, 4.3, 4, 2)
    (7, 4.3, 5, 9)
    (3, 4.3, 8, 5)
    (8, 1.2, 4, 7)

到目前为止,我尝试使用这样的自定义Comparator

    class TupleComparator implements Comparator<Tuple4<Integer, Double, Long, Integer>>, Serializable {

        private static final long serialVersionUID = 1L;

        @Override
        public int compare(Tuple4<Integer, Double, Long, Integer> v1,
        Tuple4<Integer, Double, Long, Integer> v2) {

        if(v1._2().compareTo(v2._2()) == 0){
            return v1._3().compareTo(v2._3());
        }
            return - v1._2().compareTo(v2._2());
        }
    }

但是为了使用自定义比较器,我需要使用sortByKey函数。

所以我需要做一把钥匙。 (因为正常的sortBy函数不带比较器)。

如果我然后尝试应用我的比较器:

   revenue.keyBy(x -> x._2()).groupByKey().sortByKey(new TupleComparator(), false, 1);

我得到:“方法sortByKey ...不适用于参数(TupleComparator,boolean,int)”

这就是我被困住的地方。我不确定我所做的是对的还是如何使我的比较器工作。 (我不太熟悉自定义比较器)。

也许有更好的方法来实现这一目标?我知道在Scala中做起来更简单。

但是我需要在Java中使用RDD API。

1 个答案:

答案 0 :(得分:2)

您需要分两步完成。首先,您需要按Double值的降序对RDD进行排序。

JavaRDD<Tuple4<Integer, Double, Long, Integer>> firstSortRDD = revenue.sortBy( new Function<Tuple4<Integer, Double, Long, Integer>, Integer>() {
        @Override
        public Integer call(Tuple4<Integer, Double, Long, Integer> value) throws Exception {
            return value._2().intValue();
        }
    }, false, 1 );

您需要的下一个排序是按Long值的升序排列,这取决于Double值的顺序。因此,您必须创建一个密钥Tuple2<Double,Long>。现在,您可以使用sortByKey方法并传递具有自定义逻辑的比较器进行比较。

JavaRDD<Tuple4<Integer,Double,Long,Integer>> secondSortRDD = firstSortRDD.keyBy(new Function<Tuple4<Integer, Double, Long, Integer>, Tuple2<Double, Long>>(){
        @Override
        public Tuple2<Double, Long> call(Tuple4<Integer, Double, Long, Integer> value) throws Exception {
            return new Tuple2(value._2(),value._3());
        }}).sortByKey(new TupleComparator()).values();

这是Tuple2<Double,Long>

的比较器类
class TupleComparator implements Comparator<Tuple2<Double,Long>>, Serializable {
private static final long serialVersionUID = 1L;
@Override
public int compare(Tuple2<Double, Long> v1, Tuple2<Double, Long> v2) {
    if (v1._1().compareTo(v2._1()) == 0) {
        return v1._2().compareTo(v2._2());
    }
        return  v2._2().compareTo(v1._2());
    }
}