用Spark完成复杂TopN计算的两种逻辑
如果有商品品类的数据pairRDD(categoryId,clickCount_orderCount_payCount),用Spark完成Top5,你会怎么做?
这里假设使用Java语言进行编写,那么你有两种思路:
1.简化成RDD(categoryObject),其中categoryObject实现了java.lang.Comparable.然后使用top(5)获得topN
2.转换成PairRDD(categoryKey,info),其中categoryKey实现了scala.math.Ordered。然后进行sortByKey之后再take(5).
注意:
1)top(n)函数在Java的Spark API中内部调用的比较器是java.lang.Comparable进行比较.
2)而sortByKey函数在Java的Spark API中依然调用scala.math.Ordered进行比较.
相比之下,思路2的空间和时间都不如思路1,但是如果我们需要sort结果的过程中顺便获得topN,则使用思路2更好一些。
思路1实现:
CategoryObject:
package com.stan.core.spark.userAction; import java.io.Serializable; public class ComparableCategoryObject
implements Comparable<ComparableCategoryObject>, Serializable {
String categoryId;
Long clickCategoryCount;
Long orderCategoryCount;
Long defrayCategoryCount; @Override
public int compareTo(ComparableCategoryObject o) {
long compareNum =
(this.defrayCategoryCount - o.defrayCategoryCount) * 10000
+
(this.orderCategoryCount - o.orderCategoryCount) * 100
+
(this.clickCategoryCount - o.clickCategoryCount) * 1;
return (int)(compareNum%1000);
} @Override
public String toString() {
return "ComparableCategoryObject{" +
"categoryId='" + categoryId + '\'' +
", clickCategoryCount=" + clickCategoryCount +
", orderCategoryCount=" + orderCategoryCount +
", defrayCategoryCount=" + defrayCategoryCount +
'}';
} public String getCategoryId() {
return categoryId;
} public void setCategoryId(String categoryId) {
this.categoryId = categoryId;
} public Long getClickCategoryCount() {
return clickCategoryCount;
} public void setClickCategoryCount(Long clickCategoryCount) {
this.clickCategoryCount = clickCategoryCount;
} public Long getOrderCategoryCount() {
return orderCategoryCount;
} public void setOrderCategoryCount(Long orderCategoryCount) {
this.orderCategoryCount = orderCategoryCount;
} public Long getDefrayCategoryCount() {
return defrayCategoryCount;
} public void setDefrayCategoryCount(Long defrayCategoryCount) {
this.defrayCategoryCount = defrayCategoryCount;
}
}
具体调用方法:
// 1.封装
JavaRDD<ComparableCategoryObject> comparableCategoryObjectJavaRDD =
categoryId2allCount.map(
new Function<Tuple2<String, String>, ComparableCategoryObject>() {
@Override
public ComparableCategoryObject call(Tuple2<String, String> stringStringTuple2) throws Exception {
String categoryId = stringStringTuple2._1;
String allCount = stringStringTuple2._2;
String[] tmpAllCountSplited = allCount.split("_");
Long clickCount = Long.valueOf(tmpAllCountSplited[0]);
Long orderCount = Long.valueOf(tmpAllCountSplited[1]);
Long defrayCount = Long.valueOf(tmpAllCountSplited[2]);
ComparableCategoryObject comparableCategoryObject =
new ComparableCategoryObject();
comparableCategoryObject.setCategoryId(categoryId);
comparableCategoryObject.setClickCategoryCount(clickCount);
comparableCategoryObject.setOrderCategoryCount(orderCount);
comparableCategoryObject.setDefrayCategoryCount(defrayCount);
return comparableCategoryObject;
}
}
);
// 2.top(5)
List<ComparableCategoryObject> top10Categorys = comparableCategoryObjectJavaRDD.top(5);
思路2实现:
CategoryKey:
package com.stan.core.spark.userAction; import scala.Serializable;
import scala.math.Ordered; /**
* 用于按照
* (clickCategoryCount,orderCategoryCount,defrayCategoryCount)的优先级排序
*/
public class ComparableCategoryKey
// scala中可比较,以便于进行RDD排序
implements Ordered<ComparableCategoryKey>, Serializable {
String categoryId;
Long clickCategoryCount;
Long orderCategoryCount;
Long defrayCategoryCount; /**
* 计算比较数
*
* 因为优先级为 : 先比较支付量,若支付量相同,则比较下单量,若下单量相同,则继续比较点击量
* 所以我在进行比较的时候直接使用 比较值 = 支付量差 * 10000 + 下单量差 * 100 + 点击量差
* 若比较值小于 0 ,则小于,若比较值大于0 , 则大于,若比较值等于0,则等于
* @param comparableCategoryWithAllCount
* @return
*/
public long computeCompareNum(ComparableCategoryKey comparableCategoryWithAllCount){
long compareNum =
(this.defrayCategoryCount - comparableCategoryWithAllCount.defrayCategoryCount) * 10000
+
(this.orderCategoryCount - comparableCategoryWithAllCount.orderCategoryCount) * 100
+
(this.clickCategoryCount - comparableCategoryWithAllCount.clickCategoryCount) * 1;
return compareNum;
} @Override
public int compare(ComparableCategoryKey comparableCategoryWithAllCount) {
return (int)(computeCompareNum(comparableCategoryWithAllCount)%1000);
} @Override
public boolean $less(ComparableCategoryKey comparableCategoryWithAllCount) {
return computeCompareNum(comparableCategoryWithAllCount) < 0;
} @Override
public boolean $greater(ComparableCategoryKey comparableCategoryWithAllCount) {
return computeCompareNum(comparableCategoryWithAllCount) > 0;
} @Override
public boolean $less$eq(ComparableCategoryKey comparableCategoryWithAllCount) {
return computeCompareNum(comparableCategoryWithAllCount) <= 0;
} @Override
public boolean $greater$eq(ComparableCategoryKey comparableCategoryWithAllCount) {
return computeCompareNum(comparableCategoryWithAllCount) >= 0;
} @Override
public int compareTo(ComparableCategoryKey comparableCategoryWithAllCount) {
return (int)(computeCompareNum(comparableCategoryWithAllCount)%1000);
} public String getCategoryId() {
return categoryId;
} public void setCategoryId(String categoryId) {
this.categoryId = categoryId;
} public Long getClickCategoryCount() {
return clickCategoryCount;
} public void setClickCategoryCount(Long clickCategoryCount) {
this.clickCategoryCount = clickCategoryCount;
} public Long getOrderCategoryCount() {
return orderCategoryCount;
} public void setOrderCategoryCount(Long orderCategoryCount) {
this.orderCategoryCount = orderCategoryCount;
} public Long getDefrayCategoryCount() {
return defrayCategoryCount;
} public void setDefrayCategoryCount(Long defrayCategoryCount) {
this.defrayCategoryCount = defrayCategoryCount;
} @Override
public String toString() {
return "ComparableCategoryKey{" +
"categoryId='" + categoryId + '\'' +
", clickCategoryCount=" + clickCategoryCount +
", orderCategoryCount=" + orderCategoryCount +
", defrayCategoryCount=" + defrayCategoryCount +
'}';
}
}
具体的调用过程:
// 1.封装成(categoryKey,info)
JavaPairRDD<ComparableCategoryKey,String> comparableCategory2AllCountRDD =
categoryId2allCount.mapToPair(
new PairFunction<Tuple2<String, String>, ComparableCategoryKey,String>() {
@Override
public Tuple2<ComparableCategoryKey,String> call(Tuple2<String, String> stringStringTuple2) throws Exception {
String categoryId = stringStringTuple2._1;
String allCount = stringStringTuple2._2;
String[] tmpAllCountSplited = allCount.split("_");
Long clickCount = Long.valueOf(tmpAllCountSplited[0]);
Long orderCount = Long.valueOf(tmpAllCountSplited[1]);
Long defrayCount = Long.valueOf(tmpAllCountSplited[2]);
ComparableCategoryKey comparableCategoryWithAllCount =
new ComparableCategoryKey();
comparableCategoryWithAllCount.setCategoryId(categoryId);
comparableCategoryWithAllCount.setClickCategoryCount(clickCount);
comparableCategoryWithAllCount.setOrderCategoryCount(orderCount);
comparableCategoryWithAllCount.setDefrayCategoryCount(defrayCount);
return new Tuple2<>(comparableCategoryWithAllCount,allCount);
}
}
);
// 2.sortByKey 排序
comparableCategory2AllCountRDD.sortByKey(); // 3.获取前五
List<Tuple2<ComparableCategoryKey,String>> top10Categorys = comparableCategory2AllCountRDD.take(5);
用Spark完成复杂TopN计算的两种逻辑的更多相关文章
- Spark Streaming中空batches处理的两种方法(转)
原文链接:Spark Streaming中空batches处理的两种方法 Spark Streaming是近实时(near real time)的小批处理系统.对给定的时间间隔(interval),S ...
- 【Spark篇】---SparkStreaming+Kafka的两种模式receiver模式和Direct模式
一.前述 SparkStreamin是流式问题的解决的代表,一般结合kafka使用,所以本文着重讲解sparkStreaming+kafka两种模式. 二.具体 1.Receiver模式 原理图 ...
- spark streaming 接收kafka消息之一 -- 两种接收方式
源码分析的spark版本是1.6. 首先,先看一下 org.apache.spark.streaming.dstream.InputDStream 的 类说明: This is the abstrac ...
- 第一章:1-20、试计算以下两种情况的发送时延和传播时延: (1) 数据长度为107bit,数据发送速率为100kbit/s,传播距离为1000km,信号在媒体上 的传播速率为2×108m/s。 (2) 数据长度为103bit,数据发送速率为1Gbit/s,传输距离和信号在媒体上的传播速率同 上。
<计算机网络>谢希仁著第四版课后习题答案答: 1):发送延迟=107/(100×1000)=100s 传播延迟=1000×1000/(2×108)=5×10-3s=5ms ...
- spark提交任务的两种的方法
在学习Spark过程中,资料中介绍的提交Spark Job的方式主要有两种(我所知道的): 第一种: 通过命令行的方式提交Job,使用spark 自带的spark-submit工具提交,官网和大多数参 ...
- sparkStreaming读取kafka的两种方式
概述 Spark Streaming 支持多种实时输入源数据的读取,其中包括Kafka.flume.socket流等等.除了Kafka以外的实时输入源,由于我们的业务场景没有涉及,在此将不会讨论.本篇 ...
- 编译spark源码 Maven 、SBT 2种方式编译
由于实际环境较为复杂,从Spark官方下载二进制安装包可能不具有相关功能或不支持指定的软件版本,这就需要我们根据实际情况编译Spark源代码,生成所需要的部署包. Spark可以通过Maven和SBT ...
- Spark源码剖析 - 计算引擎
本章导读 RDD作为Spark对各种数据计算模型的统一抽象,被用于迭代计算过程以及任务输出结果的缓存读写.在所有MapReduce框架中,shuffle是连接map任务和reduce任务的桥梁.map ...
- spark 例子groupByKey分组计算
spark 例子groupByKey分组计算 例子描述: [分组.计算] 主要为两部分,将同类的数据分组归纳到一起,并将分组后的数据进行简单数学计算. 难点在于怎么去理解groupBy和groupBy ...
随机推荐
- cocos creator使用anysdk接入admob广告教程
http://lolling787.lofter.com/post/1f5b6553_12925042 cocos creator使用anysdk接入admob广告
- Linux系统——MHA-Atlas-MySQL高可用集群
Linux系统——MHA-Atlas-MySQL高可用集群 MHA MHA介绍MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,是一套优秀的 ...
- Oracle函数中对于NO_DATA_FOUND异常处理的研究
一直以来有一个困惑,一直没解决,昨天一哥们问我这个问题,决心弄清楚,终于得到了答案.先看下面这个函数: create or replace function fn_test(c_xm varchar) ...
- Java IO和Java NIO 和通道 在文件拷贝上的性能差异分析
1. 在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区 ...
- Redis批量导入数据的方法
有时候,我们需要给redis库中插入大量的数据,如做性能测试前的准备数据.遇到这种情况时,偶尔可能也会懵逼一下,这里就给大家介绍一个批量导入数据的方法. 先准备一个redis protocol的文件( ...
- 自己动手写java锁
1.LockSupport的park和unpark方法的基本使用,以及对线程中断的响应性 LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞原语.java锁和同步器 ...
- python locust 性能测试:HttpSession
官网解释:用于在请求之间执行Web请求和保留(会话)cookie的类(以便能够登录和退出网站):记录每个请求,以便locust可以显示统计信息: from locust import TaskSet, ...
- Tensorflow object detection API 搭建属于自己的物体识别模型
一.下载Tensorflow object detection API工程源码 网址:https://github.com/tensorflow/models,可通过Git下载,打开Git Bash, ...
- Tomcat 控制台UTF-8乱码问题
1.修改cmd的编码格式 快捷键win+R打开运行程序,输入regedit打开注册表,找到以下路劲并且修改. [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Comman ...
- Object.prototype的成员介绍
3.Object.prototype的成员介绍 Object.prototype是js中所有的对象的祖宗 Object.prototype中所有的成员都可以被js中所有的对 ...