Spark实践 -- 夜出顾客服务分析 (2)

由于第二版的实现中的List太过冗余,所以第三版的实现在这问题上做了改进。
通过subtractByKey算子过滤掉白天出现过的所有顾客。然后进行后续的处理中,计算的就都是在夜出范围内且白天没出现过的顾客了。

// 获取白天出现过的顾客列表 JavaPairRDD<String, String> rdd = df.toJavaRDD().mapToPair(new PairFunction<Row, String, String>() { @Override public Tuple2<String, String> call(Row row) throws Exception { String[] strAry = Strsplit.splitByWholeSeparator(row.getString(1), " ", -1, true); // 下面第一重if是判断 昼伏夜出的范围, 第二重if是判断车辆在不在范围内 // nightTimeS < nightTimeE if(nightTimeS.compareTo(nightTimeE) < 0){ if(strAry[1].compareTo(nightTimeS) > 0 && strAry[1].compareTo(nightTimeE) < 0){ return new Tuple2<>("0", "0"); }else{ return new Tuple2<>(row.getString(0), row.getString(1)); } }else{ // nightTimeS > nightTimeE (包括三种情况:1,22:00 - 00:00 2,00:00 - 02:00 3. 22:00 - 02:00 其实也可以归为一种情况,前两种都是第三种的特例) if(strAry[1].compareTo(nightTimeS)> 0 || strAry[1].compareTo(nightTimeE) < 0){ return new Tuple2<>("0", "0"); } else { return new Tuple2<>(row.getString(0), row.getString(1)); } } } }); // 获取全部顾客列表 JavaPairRDD<String, String> rdd2 = df.toJavaRDD().mapToPair(new PairFunction<Row, String, String>() { @Override public Tuple2<String, String> call(Row row) throws Exception { return new Tuple2<>(row.getString(0), row.getString(1)); } }); // 做差集,获得只在所求的夜出时间段内的顾客名及时间 <userName, capDate> JavaPairRDD<String, String> rdd3 = rdd2.subtractByKey(rdd); JavaPairRDD<String, Integer> pairRdd = rdd3.mapToPair(new PairFunction<Tuple2<String, String>, String, Integer>() { //与版本二的实现相同 }); 第四版 在mapTopair的过程中直接赋极小值

第三版实现性能得到了较大的提高,但是还不够好,因为其执行过程使用的转换过多。

下面的第四版实现为了减少转换的使用,就恢复到第一版的实现中。先对夜出时间的逻辑判断增强;另外,由于想到第一版的实现中最后的filter算子中需要value值为大于0才算夜出顾客,所以在mapToPair的过程中,每当得到白天出现的顾客A时就将它的value值设为一个较小的值,在后面的reduceByKey算子的执行过程中将晚上又再次出现的A的value值给抹平。那么最后的filter算子就能将白天出现过的顾客去除掉了!

下面就是具体实现,只是将版本一中的
return new Tuple2<String, Integer>(String.format("%s,%s",userName, strAry[0]), 0);
修改成
return new Tuple2<String, Integer>(String.format("%s,%s",userName,strAry[0]), -10000);
这样实现有些取巧,但是改动比较小,在性能上表现也可以在10秒内。

JavaPairRDD<String, Integer> pairRdd = df.toJavaRDD().mapToPair(new PairFunction<Row, String, Integer>() { @Override public Tuple2<String, Integer> call(Row row) throws Exception { String userName = row.getString(0); String[] strAry = Strsplit.splitByWholeSeparator(row.getString(1), " ", -1, true); if(nightTimeS.compareTo(nightTimeE) < 0){ if(strAry[1].compareTo(nightTimeS) > 0 && strAry[1].compareTo(nightTimeE) < 0){ if(strAry[1].compareTo("24:00:00") < 0 && strAry[1].compareTo("12:00:00") > 0){ return new Tuple2<String, Integer>(String.format("%s,%s",userName,strAry[0]), 1); }else{ Date preDate = DateUtil.parse(strAry[0], "yyyy-MM-dd"); String preDate_s = DateUtil.format(DateUtil.addDays(preDate, -1), "yyyy-MM-dd"); return new Tuple2<String, Integer>(String.format("%s,%s",userName,preDate_s), 1); } }else{ // 白天出现的顾客的value设置为-10000 return new Tuple2<String, Integer>(String.format("%s,%s",userName,strAry[0]), -10000); } }else{ if(strAry[1].compareTo(nightTimeS) > 0){ return new Tuple2<String, Integer>(String.format("%s,%s",userName,strAry[0]), 1); } else if(strAry[1].compareTo(nightTimeE) < 0){ Date preDate = DateUtil.parse(strAry[0], "yyyy-MM-dd"); String preDate_s = DateUtil.format(DateUtil.addDays(preDate, -1), "yyyy-MM-dd"); return new Tuple2<String, Integer>(String.format("%s,%s",userName,preDate_s), 1); } else { // 白天出现的顾客的value设置为-10000 return new Tuple2<String, Integer>(String.format("%s,%s",userName,strAry[0]), -10000); } } } }); 总结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjggz.html