用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 ...
随机推荐
- FG面经: Interval问题合集
How to insert interval to an interval list. List is not sorted O(N) solution: package fb; import jav ...
- C#调用java方法踩坑记
首先,我的java代码写了一个遗传算法,这是我硕士毕业论文的核心算法,项目是基于C#的web项目.但是现在又不想用C#重写遗传算法代码,于是就想用C#去调用java的代码.在网上找了方法,一般有两种: ...
- CentOS 7 安装配置KVM 通过KVM安装CentOS系统
搭建环境 : CentOS 7 [root@KVM ~]# systemctl stop firewalld [root@KVM ~]# systemctl disable firewalld [ro ...
- spring boot 整合js css 静态文件
一,添加配置 spring: application: name: interview-server resources: static-locations: file:config/statics ...
- Delphi中PointerMath指令
Type Switch Syntax {$POINTERMATH ON} or {$POINTERMATH OFF} Default {$POINTERMATH OFF} Sc ...
- Machine Learning 第一二周
# ML week 1 2 一.关于machine learning的名词 学习 从无数数据提供的E:experience中找到一个函数使得得到T:task后能够得到P:prediction 监督学习 ...
- 多个for循环嵌套会影响速度
在复现Meta-SR的过程中,发现如果嵌套多个for 循环会使速度过慢.这是下面实验得出的结论: import time t1 = time.time() a = range(3000) b = ra ...
- 作业(更新ing)
暴政警告 2019.4.19 1.YBT完成 7 道题目(1)广搜 3 道 (2)最短路 4 道 2.写至少 2 篇博客 (据说集中精力,一个上午/下午就能写完) 1. 一个 又一个 球细胞数目 ...
- CC2530的Flash
CC2530F256内部集成一个增强型8051单片机,拥有8 KB SRAM和256 KB内部Flash存储器.内部Flash主要用来保存程序代码和常量数据.由于传统8051代码存储空间寻址范围只有6 ...
- python简单制作GIF
第一步安装工具:imageio (已安装好的页面) 第二步:打开python 插入代码,代码如下. import imageio savename = "C://Users//Thinkpa ...