用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 ...
随机推荐
- c# 设置开机启动
private static RegistryKey _rlocal = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Wi ...
- windows10上安装mysql(详细步骤)
2016年09月06日 08:09:34 阅读数:46198 环境:windwos 10(1511) 64bit.mysql 5.7.14 时间:2016年9月5日 一.下载mysql 1. 在浏览器 ...
- carbondata-summary
源码 http://www.zhuyongpeng.cn/1699.html 融合数据白皮书:Apache CarbonData成为主流融合存储技术 http://cloud.yesky.com/46 ...
- windows CMD常用命令
命令简介 cmd是command的缩写.即命令行 . 虽然随着计算机产业的发展,Windows 操作系统的应用越来越广泛,DOS 面临着被淘汰的命运,但是因为它运行安全.稳定,有的用户还在使用,所以一 ...
- ajax的网上解析
/* 用XMLHTTPRequest来进行ajax异步数据交交互*/ 主要有几个步骤: //1.创建XMLHTTPRequest对象 //最复杂的一步 if (window.XMLHttpReques ...
- volatile CAS区别
- cnetos7设置中文显示及中文输入法
Centos7安装的时候即使选择了中文安装,因为安装后并没有GUI,即使后来安装GUI后默认依旧是英文显示. 输入locale后显示的是 永久修改成中文:编辑/etc/profile.d/lang.s ...
- centos7安装配置jdk
① java -version 可以查看系统自带的openjdk版本信息 ② rpm -qa | grep java 查看系统自带的Java文件 ③ 卸载文件(noarch文件可以不用删除) -- ...
- SQL查询数据时报错
在开发过程中如果查询报如下的错误: org.springframework.jdbc.UncategorizedSQLException: Error attempting to get column ...
- python模块的使用
这位老师的文章说的很清楚:模块 这里我只说一下,我在使用过程中的一些注意事项. 比如,我创建了一个包,该包下面有两个模块:model1和model2,如下图 那么我们再python中怎样去使用自己创建 ...