我很兴奋,需要用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。
答案 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());
}
}