首先设定路口超过70km/h为超速车辆
.aggregate(new AggregateFunction<
Tuple4<String, Integer, Double, Long>, // 输入元素类型
Tuple6<String, Double, Double, Double, Long, Long>, // 累加器类型
Tuple5<String, Long, Long, Double, Double> // 输出元素类型
>() {
@Override
public Tuple6<String, Double, Double, Double, Long, Long> createAccumulator() {
return Tuple6.of("", 0.0, 0.0, 0.0, 0L, 0L);
}
@Override
public Tuple6<String, Double, Double, Double, Long, Long> add(
Tuple4<String, Integer, Double, Long> value,
Tuple6<String, Double, Double, Double, Long, Long> accumulator) {
// 第一个元素为车牌号,初始化车牌号和进入路口时间
if (accumulator.f0.isEmpty() && value.f1 == 1) {
accumulator.f0 = value.f0;
accumulator.f4 = value.f3;
}
// 如果车辆正在路口内超速,则将其纳入计算
if (accumulator.f0.equals(value.f0) && value.f1 == 1 && value.f2 > 70.0) {
// 求出车辆在路口内的速度总和
accumulator.f3 += value.f2;
// 更新最高速度
if (value.f2 > accumulator.f2) {
accumulator.f2 = value.f2;
}
// 更新路口内时间或离开路口时间
if (value.f1 == 1) {
accumulator.f5 = value.f3;
} else {
accumulator.f4 = value.f3;
}
}
return accumulator;
}
@Override
public Tuple5<String, Long, Long, Double, Double> getResult(
Tuple6<String, Double, Double, Double, Long, Long> accumulator) {
// 结果为:车牌号,进入路口时间,离开路口时间,路口内平均速度,最高速度
if (accumulator.f3 > 0) {
double avgSpeed = accumulator.f3 / (accumulator.f5 - accumulator.f4) * 1000.0;
return Tuple5.of(accumulator.f0, accumulator.f4, accumulator.f5, avgSpeed, accumulator.f2);
} else {
return null;
}
}
@Override
public Tuple6<String, Double, Double, Double, Long, Long> merge(
Tuple6<String, Double, Double, Double, Long, Long> a,
Tuple6<String, Double, Double, Double, Long, Long> b) {
throw new UnsupportedOperationException("不支持merge操作");
}
})
在上面的示例中,我们定义了一个 Aggregate Function 累加器,其中 createAccumulator
方法用于创建初始累加器,add
方法用于将元素累加到累加器中,getResult
方法用于返回最终的聚合结果,merge
方法用于合并不同分区的累加器。
在这个示例中,createAccumulator
方法返回 0,因为我们要对分组后的元素求和。add
方法将每个元素的分数累加到累加器中。getResult
方法返回最终的累加值。merge
方法只需要将两个累加器相加即可,因为同一个 Key 的元素只会被分配到同一个分区中。
需要注意的是,上述代码中的累加器函数是对 Key 分组之后的数据进行聚合操作的,因此必须先使用 keyBy()
方法将数据按照 Key 进行分组,否则会抛出运行时异常。