环境
  虚拟机:VMware 10
  Linux版本:CentOS-6.5-x86_64
  客户端:Xshell4
  FTP:Xftp4
  jdk1.8
  scala-2.10.4(依赖jdk1.8)
  spark-1.6

一、PV & UV

  PV是网站分析的一个术语,用以衡量网站用户访问的网页的数量。对于广告主,PV值可预期它可以带来多少广告收入。一般来说,PV与来访者的数量成正比,但是PV并不直接决定页面的真实来访者数量,如同一个来访者通过不断的刷新页面,也可以制造出非常高的PV。

1、什么是PV值
PV(page view)即页面浏览量或点击量,是衡量一个网站或网页用户访问量。具体的说,PV值就是所有访问者在24小时(0点到24点)内看了某个网站多少个页面或某个网页多少次。PV是指页面刷新的次数,每一次页面刷新,就算做一次PV流量。
度量方法就是从浏览器发出一个对网络服务器的请求(Request),网络服务器接到这个请求后,会将该请求对应的一个网页(Page)发送给浏览器,从而产生了一个PV。那么在这里只要是这个请求发送给了浏览器,无论这个页面是否完全打开(下载完成),那么都是应当计为1个PV。

package com.wjy.test;

import java.util.List;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction; import scala.Tuple2; public class Pv { public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("PV");
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<String> rdd = sc.textFile("./data/pvuvdata"); //根据PV定义 某个页面/网址的访问数量 将每一条记录根据网址解析出一条访问量
JavaPairRDD<String, Integer> ipwebrdd = rdd.mapToPair(new PairFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Tuple2<String, Integer> call(String line) throws Exception {
//7.213.213.208 吉林 2018-03-29 1522294977303 1920936170939152672 www.dangdang.com Login
String[] ss = line.split("\t");
return new Tuple2<String, Integer>(ss[],);
}
}); //累加页面访问量
JavaPairRDD<String, Integer> mapToPair = ipwebrdd.reduceByKey(new Function2<Integer, Integer, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
}).mapToPair(new PairFunction<Tuple2<String,Integer>, Integer, String>() {
private static final long serialVersionUID = 1L;
//换个 用于按照整数key排序
@Override
public Tuple2<Integer, String> call(Tuple2<String, Integer> tuple)
throws Exception {
return tuple.swap();
}
}).sortByKey(false).mapToPair(new PairFunction<Tuple2<Integer,String>, String, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Tuple2<String, Integer> call(Tuple2<Integer, String> tuple)
throws Exception {
return tuple.swap();
}
}); List<Tuple2<String, Integer>> list = mapToPair.take();
for(Tuple2<String, Integer> t:list){
System.out.println(t);
} sc.stop();
} }

结果:

(www.baidu.com,)
(www.dangdang.com,)
(www.suning.com,)
(www.mi.com,)
(www.taobao.com,)

2、什么是UV值
UV(unique visitor)即独立访客数,指访问某个站点或点击某个网页的不同IP地址的人数。在同一天内,UV只记录第一次进入网站的具有独立IP的访问者,在同一天内再次访问该网站则不计数。UV提供了一定时间内不同观众数量的统计指标,而没有反应出网站的全面活动。

package com.wjy.test;

import java.util.List;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction; import scala.Tuple2; public class Uv { /**
* 根据IP网址来确定唯一用户访问 然后排重 累计
* @param args
*/
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("UV");
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<String> rdd = sc.textFile("./data/pvuvdata"); JavaPairRDD<String, Integer> rdd2 = rdd.mapToPair(new PairFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Tuple2<String, Integer> call(String line) throws Exception {
String[] split = line.split("\t");
return new Tuple2<String, Integer>(split[0]+"_"+split[5],1);
}
})
.distinct()
.mapToPair(new PairFunction<Tuple2<String,Integer>, String, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Tuple2<String, Integer> call(Tuple2<String, Integer> tuple)
throws Exception {
return new Tuple2<String, Integer>(tuple._1.split("_")[1],1);
}
}); //累加
JavaPairRDD<String, Integer> rdd3 = rdd2.reduceByKey(new Function2<Integer, Integer, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1+v2;
}
})
.mapToPair(new PairFunction<Tuple2<String,Integer>, Integer, String>() {
private static final long serialVersionUID = 1L;
//反转 数值做KEY 用于排序
@Override
public Tuple2<Integer, String> call(Tuple2<String, Integer> tuple)
throws Exception {
return tuple.swap();
}
})
.sortByKey(false)//降序排序
.mapToPair(new PairFunction<Tuple2<Integer,String>, String, Integer>() {
private static final long serialVersionUID = 1L;
//排序之后 反转回来
@Override
public Tuple2<String, Integer> call(Tuple2<Integer, String> tuple)
throws Exception {
return tuple.swap();
}
}); //取前5个元素
List<Tuple2<String, Integer>> list = rdd3.take(5);
for(Tuple2<String, Integer> t:list){
System.out.println(t);
} sc.stop();
} }

结果:

(www.baidu.com,15830)
(www.suning.com,15764)
(www.mi.com,15740)
(www.jd.com,15682)
(www.dangdang.com,15641)

二、二次排序

对于两列以上的数据,要求对第一列排序之后,之后的列也要依次排序,思路就是:先对第一列进行排序,对于第一列数值相同,再对第二列进行排序。

举例:

待排序数据:secondSort.txt


package com.wjy.test;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.VoidFunction; import scala.Tuple2; public class SecondSort{ public static void main(String[] args) {
SparkConf conf = new SparkConf();
conf.setMaster("local").setAppName("SecondSort");
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<String> rdd = sc.textFile("./data/secondSort.txt"); //转成K-V格式
//PairFunction 入参1-rdd的一行记录 入参2 入参3是call的出参
JavaPairRDD<SecondSortKey, String> mapToPair = rdd.mapToPair(new PairFunction<String, SecondSortKey, String>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<SecondSortKey, String> call(String line)
throws Exception
{
String[] sps = line.split(" ");
int first = Integer.valueOf(sps[0]);
int second = Integer.valueOf(sps[1]);
SecondSortKey ss = new SecondSortKey(first,second);
return new Tuple2<SecondSortKey, String>(ss,line);
}
}); //sortByKey 会使用key也就是SecondSortKey的compareTo方法
mapToPair.sortByKey(false).foreach(new VoidFunction<Tuple2<SecondSortKey,String>>() {
private static final long serialVersionUID = 1L; @Override
public void call(Tuple2<SecondSortKey, String> tuple) throws Exception {
System.out.println(tuple._2);
}
});
    
sc.stop();
    
     } }

对于KEY自定义类型 实现comparable接口 实现comparTo方法

package com.wjy.test;

import java.io.Serializable;

public class SecondSortKey  implements Serializable ,Comparable<SecondSortKey>{

    private static final long serialVersionUID = 1L;

    private int first;
private int second; public SecondSortKey(int first,int second)
{
super();
this.first=first;
this.second=second;
} public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
} @Override
public int compareTo(SecondSortKey o) { //先比较第一个数值 如果相同再比较第二个值 否则直接返回第一个值的比较结果
if (getFirst()-o.getFirst() == 0)
{
return getSecond() - o.getSecond();
}
else
{
return getFirst()-o.getFirst();
}
} }

排序结果:

8 654
8 123
6 5
5 432
5 121
5 2
4 123
3 98
3 54
3 1
1 4

三、分组取topN

对于多组数据,去每一组数据前N个数据,比如列出每个班级的前三名等等问题。
解决的思路:先分组,然后每一组排序,取前N个。
案例:有三个班级的分数清单scores.txt,取出每班前三名。

class1    100
class2 85
class3 70
class1 102
class2 65
class1 45
class2 85
class3 70
class1 16
class2 88
class1 95
class2 37
class3 98
class1 99
class2 23

groupByKey+排序算法:

package com.wjy.test;

import java.util.Iterator;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.VoidFunction; import scala.Tuple2; public class TopNtest { public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("TopOs");
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<String> rdd = sc.textFile("./data/scores.txt"); //转成K-V格式 方便下一步分组和排序
//PairFunction 入参1rdd的一行数据 入参2、3是call的出参元素
JavaPairRDD<String, Integer> mapToPair = rdd.mapToPair(new PairFunction<String, String, Integer>() {
private static final long serialVersionUID = 1L;
@Override
public Tuple2<String, Integer> call(String line) throws Exception {
String[] ss = line.split("\t");
return new Tuple2<String, Integer>(ss[0],Integer.valueOf(ss[1]));
}
}); //使用groupByKey 将相同班级的数据放在一个集合里
mapToPair.groupByKey().foreach(new VoidFunction<Tuple2<String,Iterable<Integer>>>() {
private static final long serialVersionUID = 1L;
@Override
public void call(Tuple2<String, Iterable<Integer>> tuple) throws Exception {
String classname = tuple._1;
Iterator<Integer> it = tuple._2.iterator();
Integer[] top3 = new Integer[3];
while(it.hasNext())
{
Integer score = it.next();
//排序
for (int i = 0; i < top3.length; i++)
{
if(top3[i] == null)
{
top3[i] = score;
break;
}
else if(score > top3[i])
{
for (int j = 2; j > i; j--)
{
top3[j] = top3[j-1];
}
top3[i] = score;
break;
}
}
}
System.out.println("classname="+classname);
for (Integer i:top3)
{
System.out.println(i);
}
}
});
sc.stop();
} }

topN 结果:

classname=class3
98
70
70
classname=class1
102
100
99
classname=class2
88
85
85

【Spark-core学习之九】 Spark案例的更多相关文章

  1. 【Spark深入学习-11】Spark基本概念和运行模式

    ----本节内容------- 1.大数据基础 1.1大数据平台基本框架 1.2学习大数据的基础 1.3学习Spark的Hadoop基础 2.Hadoop生态基本介绍 2.1Hadoop生态组件介绍 ...

  2. 【spark core学习---算子总结(java版本) (第1部分)】

    map算子 flatMap算子 mapParitions算子 filter算子 mapParttionsWithIndex算子 sample算子 distinct算子 groupByKey算子 red ...

  3. 【Spark深入学习 -12】Spark程序设计与企业级应用案例02

    ----本节内容------- 1.遗留问题答疑 1.1 典型问题解答 1.2 知识点回顾 2.Spark编程基础 2.1 Spark开发四部曲 2.2 RDD典型实例 2.3 非RDD典型实例 3. ...

  4. 【Spark深入学习 -14】Spark应用经验与程序调优

    ----本节内容------- 1.遗留问题解答 2.Spark调优初体验 2.1 利用WebUI分析程序瓶颈 2.2 设置合适的资源 2.3 调整任务的并发度 2.4 修改存储格式 3.Spark调 ...

  5. 【Spark深入学习 -13】Spark计算引擎剖析

    ----本节内容------- 1.遗留问题解答 2.Spark核心概念 2.1 RDD及RDD操作 2.2 Transformation和Action 2.3 Spark程序架构 2.4 Spark ...

  6. 【Spark 深入学习 01】 Spark是什么鬼?

    经过一段时间的学习和测试,是时候给spark的学习经历做一个总结了,对于spark的了解相对晚了写.春节期间(预计是无大事),本博准备推出20篇左右spark系列原创文章(先把牛吹出去再说) ,尽量将 ...

  7. 【Spark 深入学习 -09】Spark生态组件及Master节点HA

    ----本节内容------- 1.Spark背景介绍 2.Spark是什么 3.Spark有什么 4.Spark部署 4.1.Spark部署的2方面 4.2.Spark编译 4.3.Spark St ...

  8. spark SQL学习(认识spark SQL)

    spark SQL初步认识 spark SQL是spark的一个模块,主要用于进行结构化数据的处理.它提供的最核心的编程抽象就是DataFrame. DataFrame:它可以根据很多源进行构建,包括 ...

  9. 【spark 深入学习 03】Spark RDD的蛮荒世界

    RDD真的是一个很晦涩的词汇,他就是伯克利大学的博士们在论文中提出的一个概念,很抽象,很难懂:但是这是spark的核心概念,因此有必要spark rdd的知识点,用最简单.浅显易懂的词汇描述.不想用学 ...

  10. 【Spark深入学习 -15】Spark Streaming前奏-Kafka初体验

    ----本节内容------- 1.Kafka基础概念 1.1 出世背景 1.2 基本原理 1.2.1.前置知识 1.2.2.架构和原理 1.2.3.基本概念 1.2.4.kafka特点 2.Kafk ...

随机推荐

  1. python让实例作用于for循环并当做list来使用

    python如果想让一个类被用于for....in  循环,类型list和tuple那样,可以实现__iter__方法. 这个方法返回一个迭代对象,python的for循环就会不断调用该迭代对象的ne ...

  2. 【中间件安全】IIS6安全加固规范

    1. 适用情况 适用于使用IIS6进行部署的Web网站. 2. 技能要求 熟悉IIS配置操作,能够利用IIS进行建站,并能针对站点使用IIS进行安全加固. 3. 前置条件 1. 根据站点开放端口.进程 ...

  3. C# IO流的操作(二)

    文件在操作系统中是以二进制(01)的形式保存到磁盘上的,在C#程序当中,我们可以通过读取流将文件读取到byte[]当中(读到内存中),也可以通过写入流将byte[]写入文件(保存到磁盘上).下面将演示 ...

  4. Hystrix入门与分析(二):依赖隔离之线程池隔离

    1.依赖隔离概述 依赖隔离是Hystrix的核心目的.依赖隔离其实就是资源隔离,把对依赖使用的资源隔离起来,统一控制和调度.那为什么需要把资源隔离起来呢?主要有以下几点: 1.合理分配资源,把给资源分 ...

  5. 基于Schema配置切面

        使用基于Schema的切面定义后,切点.增强类型的注解信息从切面类中剥离出来,原来的切面类也就蜕变为真正意义上的POJO了. 1.一个简单切面的配置 基于Schema配置的切面示例: < ...

  6. PHP 高效导入导出Excel(csv)方法之fgetcsv()和fputcsv()函数

    CSV,是Comma Separated Value(逗号分隔值)的英文缩写,通常都是纯文本文件. 一.CSV数据导入函数fgetcsv() fgetcsv() 函数从文件指针中读入一行并解析 CSV ...

  7. codeforces R 493 div2

    我蓝了!蓝了!!!蒟蒻的蓝色.日常点开friend发现竟然没几个人打??然后去div1看了一下果然学长全都去打div1了呜呜呜. 看到了久违的黄大仙,以为他今晚要上grandmaster,结果打完发现 ...

  8. 24、设计模式、webpack

    利用静态属性:长驻内存 (一) 单例模式 概念:单个实例,只有一个对象,多次创建,返回同一个对象. 单例模式的核心:==确保只有一个实例==,并提供全局访问. //利用了静态属性:长驻内存 funct ...

  9. [转] - xargs 分析

    原文出处:http://www.cnblogs.com/f-ck-need-u/p/5925923.html 学习这个xargs花了很长时间,在网上翻了很久也查了很多书关于xargs的介绍,都只是简单 ...

  10. javascript的数组之sort()

    sort()方法用in-place的算法对原数组进行排序,但不会产生新的数组.这个方法不是一个稳定的排序,默认采用的是安字符串Unicode码点进行排序的. let fruit =  ['cherri ...