ITPub博客

首页 > 大数据 > > Spark学习笔记

Spark学习笔记

作者:格伯纳 时间:2020-05-08 17:28:48 0 删除 编辑

算子

动作

count:统计RDD中元素的个数
1个
2
3
4
5
val rdd = sc.makeRDD(Array(“ hello”,“ hello”,“ hello”,“ world”))
val num = rdd.count()
println(num)
结果:
4
foreach:遍历RDD中的元素
1个
2
3
4
5
6
7
val rdd = sc.makeRDD(Array(“ hello”,“ hello”,“ hello”,“ world”))
rdd.foreach(println)
结果:
你好
你好
你好
世界
foreach分区

foreach以一条记录为单位来遍历RDD
foreachPartition以分区为单位遍历RDD
foreach和foreachPartition都是动作算子
map和mapPartition可以与它们做类比,但map和mapPartitions是转换算子

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//设置rdd的分区数为2
VAL RDD = sc.parallelize(1至6,2)
rdd.foreachPartition(x => {
  println(“来自分区的数据:”)
  而(x.hasNext){
    println(x.next())
  }
})
结果:
分区中的数据:
1个
2
3
分区中的数据:
4
5
6
collect:把运行结果拉回到Driver端
1个
2
3
4
5
6
7
8
9
10
11
val rdd = sc.makeRDD(Array(
  (5,“汤姆”),(10,“杰德”),(3,“托尼”),(2,“杰克”)
))
val resultRDD = rdd.sortByKey()
val list = resultRDD.collect()
list.foreach(println)
结果:
(2,杰克)
(3,贝)
(5,汤姆)
(10,杰德)
take(n):取RDD中的前n个元素
1个
2
3
4
5
val rdd = sc.makeRDD(Array(“ hello”,“ hello”,“ hello”,“ world”))
rdd.take(2).foreach(println)
结果:
你好
你好
第一:相当于take(1)
1个
2
3
4
val rdd = sc.makeRDD(Array(“ hello”,“ hello”,“ hello”,“ world”))
println(rdd.first)
结果:
你好
减少:按照指定规则聚合RDD中的元素
1个
2
3
4
5
6
VAL numArr = 阵列(1,2,3,4,5)
val rdd = sc.parallelize(numArr)
val sum = rdd.reduce(_ + _)
println(sum)
结果:
15
countByKey:统计出KV格式的RDD中相同的K的个数
1个
2
3
4
5
6
7
8
9
10
11
12
13
val rdd = sc.parallelize(Array(
  (“销售部”,“汤姆”),(“销售部”,“杰克”),(“销售部”,“鲍勃”),(“销售部”,“特里”),
  (“后勤部”,“杰克”),(“后勤部”,“ Selina”),(“后勤部”,“ Hebe”),
  (“人力部”,“ Ella”),(“人力部”,“ Harry”),
  (“开发部”,“艾伦”)
))
val结果= rdd.countByKey();
result.foreach(println)
结果:
(后勤部,3)
(开发部,1)
(销售部,4)
(人力部,2)
countByValue:统计出RDD中每个元素的个数
1个
2
3
4
5
6
7
8
9
10
11
val rdd = sc.parallelize(Array(
  “汤姆”,“杰德”,“汤姆”,
  “汤姆”,“杰德”,“杰德”,
  “汤姆”,“托尼”,“杰德”
))
val结果= rdd.countByValue();
result.foreach(println)
结果:
(汤姆,4岁)
(托尼,1)
(杰德,4)

转变

过滤器:过滤
1个
2
3
4
val rdd = sc.makeRDD(Array(“ hello”,“ hello”,“ hello”,“ world”))
rdd.filter(!_。contains(“ hello”))。foreach(println)
结果:
世界
地图和平面地图

样本:随机抽样

样本(withReplacement:布尔值,分数:Double,种子:Long)
withReplacement:是否是放回式抽样
真实代表如果抽中A元素,之后还可以抽取A元素
false代表如果抽住了A元素,之后都不在抽取A元素
分数:抽样的比例
种子:抽样算法的初始值

1个
2
3
4
5
6
7
8
9
val rdd = sc.makeRDD(Array(
  “ hello1”,“ hello2”,“ hello3”,“ hello4”,“ hello5”,“ hello6”,
  “world1” ,“world2” ,“world3” ,“world4”
))
rdd.sample(false,0.3).foreach(println)
结果:
你好4
世界1
在数据量不大的时候,不会很准确
groupByKey和reduceByKey

sortByKey:按键进行排序
1个
2
3
4
5
6
7
8
9
10
11
val rdd = sc.makeRDD(Array(
  (5,“汤姆”),(10,“杰德”),(3,“托尼”),(2,“杰克”)
))
rdd.sortByKey()。foreach(println)
结果:
(2,杰克)
(3,贝)
(5,汤姆)
(10,杰德)
说明:
sortByKey(fasle):倒序
sortBy:自定义排序规则
1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
对象 SortByOperator {
  def main(args: Array [ String ]): Unit = {
   val conf = new SparkConf().setAppName(“ TestSortBy”).setMaster(“ local”)
    val sc = 新的 SparkContext(conf)
    val arr = 数组(
        Tuple3(190,100,“杰德”),
        Tuple3(100,202,“汤姆”),
        Tuple3(90,111,“托尼”)
    )
    val rdd = sc.parallelize(arr)
    rdd.sortBy(_._ 1).foreach(println)
    / *(90,111,托尼)
       (100,202,汤姆)
       (190,100,Jed)
     * /
    rdd.sortBy(_._ 2).foreach(println)
    / *(190,100,Jed)
       (90,111,托尼)
       (100,202,汤姆)
     * /
    rdd.sortBy(_._ 3).foreach(println)
    / *
       (190,100,Jed)
       (100,202,汤姆)
       (90,111,托尼)
     * /
    sc.stop();
  }
}
独特的:去掉重复数据

与众不同的算术实际上经历了以下步骤:

1个
2
3
4
5
6
7
8
9
10
11
12
13
val rdd = sc.makeRDD(Array(
      “你好”,
      “你好”,
      “你好”,
      “世界”
))
valdistingRDD = rdd
      .map {(_,1)}
      .reduceByKey(_ + _)
      .map(_._ 1)
distantRDD.foreach {println}
等价于:
rdd.distinct()。foreach {println}

加入

先看看SQL中的加入
假设有如下两张表:table A是左表,table B是右表

不同加入方式会有不同的结果

1.内部加入

产生的结果集是A和B的交集执行SQL:

1个
2
3
选择 * 从 TableA
INNER JOIN表B
开启 TableA.name = TableB.name

结果:

2.左外连接

产生表A的完全集,而B表中匹配的则有值,没有匹配的则以null值取代

执行SQL:

1个
2
3
选择 * 从 TableA
LEFT OUTER JOIN表B
开启 TableA.name = TableB.name

结果:

3.右外连接

产生表B的完全集,而A表中匹配的则有值,没有匹配的则以null值取代执行SQL:


1个
2
3
选择 * 从 TableA
RIGHT OUTER JOIN表B
开启 TableA.name = TableB.name

结果:

4.完全外部联接(MySQL不支持)

产生A和B的并集,但是需要注意的是,对于没有匹配的记录,继承以null做为值

执行SQL:

1个
2
3
选择 * 从 TableA
FULL OUTER JOIN表B
开启 TableA.name = TableB.name

结果:

在Spark的算子中,对两个RDD进行进行类似类似的作用
假设有两个RDD:

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
val nameList = 列表(
      (1,“ Jed”),
      (2,“汤姆”),
      (3,“鲍勃”),
      (4,“托尼”)
)
   
val SalonArr = 数组(
      (1,8000),
      (2,6000),
      (3,5000)
)
/ *
 * parallelize(Seq [T],Int num)
 *使用指定的集合(可以是List,Array等)来创建RDD
 * num指定RDD的分区数,交替为1
 *这个方法经常用于测试环境
 * join产生的RDD的分区数由分区数最多的父RDD决定
 * /
val nameRDD = sc.parallelize(nameList,2)
val salalRDD = sc.parallelize(salaryArr,3)

分别对4种join做测试:

1个
2
3
4
5
6
7
val joinRDD =名称RDD.join(salaryRDD)
joinRDD.foreach(x => {
    值 ID = x._1
    值名称= x._2._1
    瓦尔工资= x._2._2
    println(id + “ \ t” +名称+ “ \ t” +薪水)
})

结果:
1 Jed 8000
2 Tom 6000
3 Bob 5000

1个
2
3
4
5
6
7
val leftOuterJoinRDD = nameRDD.leftOuterJoin(salaryRDD)
leftOuterJoinRDD.foreach(x => {
      值 ID = x._1
      值名称= x._2._1
      瓦尔工资= x._2._2
      println(id + “ \ t” +名称+ “ \ t” +薪水)
})

结果:
1 Jed Some(8000)
2 Tom Some(6000)
3 Bob Some(5000)
4 Tony无

1个
2
3
4
5
6
7
val rightOuterJoinRDD = nameRDD.rightOuterJoin(salaryRDD)
rightOuterJoinRDD.foreach(x => {
      值 ID = x._1
      值名称= x._2._1
      瓦尔工资= x._2._2
      println(id + “ \ t” +名称+ “ \ t” +薪水)
})

结果:
1 Some(Jed)8000
2 Some(Tom)6000
3 Some(Bob)5000

1个
2
3
4
5
6
7
val fullOuterJoinRDD = nameRDD.fullOuterJoin(salaryRDD)
fullOuterJoinRDD.foreach(x => {
      值 ID = x._1
      值名称= x._2._1
      瓦尔工资= x._2._2
      println(id + “ \ t” +名称+ “ \ t” +薪水)
})

结果:
1一些(Jed)一些(8000)
2一些(Tom)一些(6000)
3一些(Bob)一些(5000)
4一些(Tony)无

union:把两个RDD进行逻辑上的合并

union这个算子关联的两个RDD必须类型一致

1个
2
3
val rdd1 = sc.makeRDD(1至10)
val rdd2 = sc.parallelize(11到20)
rdd1.union(rdd2).foreach {println}

map和mapPartitions

map()会一条记录为单位进行操作

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
val arr = 数组(“汤姆”,“鲍勃”,“托尼”,“杰里”)
//把4条数据分到两个分区中
val rdd = sc.parallelize(arr,2)
   
/ *
 *模拟把RDD中的元素写入数据库的过程
 * /
rdd.map(x => {
  println(“创建数据库连接...”)
  println(“写入数据库...”)
  println(“关闭数据库连接...”)
  println()
})。计数()
结果:
创建数据库连接...
写入数据库...
关闭数据库连接...
创建数据库连接...
写入数据库...
关闭数据库连接...
创建数据库连接...
写入数据库...
关闭数据库连接...
创建数据库连接...
写入数据库...
关闭数据库连接...

mapPartitions以分区为单位进行操作

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
/ *
 *将RDD中的数据写入到数据库中,绝大部分使用mapPartitions算子来实现
 * /
rdd.mapPartitions(x => {
  println(“创建数据库”)
  val list = new ListBuffer [ String ]()
  而(x.hasNext){
    //编写数据库
    列表+ = x.next()+ “:写入数据库”
  }
  //执行SQL语句批量插入
  list.iterator
})foreach(println)
结果:
创建数据库
汤姆:编写数据库
鲍勃:编写数据库
创建数据库
托尼:编写数据库
杰瑞:编写数据库
mapPartitionsWithIndex
1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
val dataArr = Array(“ Tom01”,“ Tom02”,“ Tom03”
                  ,“ Tom04”,“ Tom05”,“ Tom06”
                  ,“ Tom07”,“ Tom08”,“ Tom09”
                  ,“ Tom10”,“ Tom11”,“ Tom12”)
val rdd = sc.parallelize(dataArr,3);
val结果= rdd.mapPartitionsWithIndex((index,x)=> {
    val list = ListBuffer [ String ]()
    而(x.hasNext){
      列表+ = “分区:” +索引+ “内容:” + x.next
    }
    list.iterator
})
println(“分区数量:” + result.partitions.size)
val resultArr = result.collect()
为(x <-resultArr){
  println(x)
}
结果:
分区数量:3
分区:内容:Tom01
分区:内容:Tom02
分区:内容:Tom03
分区:内容:Tom04
分区:1内容:Tom05
分区:1内容:Tom06
分区:1内容:Tom07
分区:1内容:Tom08
分区:2内容:Tom09
分区:2内容:Tom10
分区:2内容:Tom11
分区:2内容:Tom12
合并:改变RDD的分区数
1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65岁
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/ *
 * false:不产生随机播放
 * true:产生随机播放
 *如果重分区的数量大于原来的分区数量,必须设置为true,否则分区数不变
 *增加分区会把原来的分区中的数据随机分配给设置的分区个数
 * /
val coalesceRdd = result.coalesce(6,true)
   
val结果= coalesceRdd.mapPartitionsWithIndex((index,x)=> {
  val list = ListBuffer [ String ]()
  而(x.hasNext){
      列表+ = “分区:” +索引+ “内容:[” + x.next + “]”
  }
  list.iterator
})
   
println(“分区数量:” + results.partitions.size)
val resultArr = results.collect()
为(x <-resultArr){
  println(x)
}
结果:
分区数量:6
分区:内容:[分区:1内容:Tom07 ]
分区:内容:[分区:2内容:Tom10 ]
分区:1内容:[分区:内容:Tom01 ]
分区:1内容:[分区:1内容:Tom08 ]
分区:1内容:[分区:2内容:Tom11 ]
分区:2内容:[分区:内容:Tom02 ]
分区:2内容:[分区:2内容:Tom12 ]
分区:3内容:[分区:内容:Tom03 ]
分区:4内容:[分区:内容:Tom04 ]
分区:4内容:[分区:1内容:Tom05 ]
分区:5内容:[分区:1内容:Tom06 ]
分区:5内容:[分区:2内容:Tom09 ]
val coalesceRdd = result.coalesce(6,fasle)的结果是:
分区数量:3
分区:内容:[分区:内容:Tom01 ]
分区:内容:[分区:内容:Tom02 ]
分区:内容:[分区:内容:Tom03 ]
分区:内容:[分区:内容:Tom04 ]
分区:1内容:[分区:1内容:Tom05 ]
分区:1内容:[分区:1内容:Tom06 ]
分区:1内容:[分区:1内容:Tom07 ]
分区:1内容:[分区:1内容:Tom08 ]
分区:2内容:[分区:2内容:Tom09 ]
分区:2内容:[分区:2内容:Tom10 ]
分区:2内容:[分区:2内容:Tom11 ]
分区:2内容:[分区:2内容:Tom12 ]
val coalesceRdd = result.coalesce(2,fasle)的结果是:
分区数量:2
分区:内容:[分区:内容:Tom01 ]
分区:内容:[分区:内容:Tom02 ]
分区:内容:[分区:内容:Tom03 ]
分区:内容:[分区:内容:Tom04 ]
分区:1内容:[分区:1内容:Tom05 ]
分区:1内容:[分区:1内容:Tom06 ]
分区:1内容:[分区:1内容:Tom07 ]
分区:1内容:[分区:1内容:Tom08 ]
分区:1内容:[分区:2内容:Tom09 ]
分区:1内容:[分区:2内容:Tom10 ]
分区:1内容:[分区:2内容:Tom11 ]
分区:1内容:[分区:2内容:Tom12 ]
val coalesceRdd = result.coalesce(2,true)的结果是:
分区数量:2
分区:内容:[分区:内容:Tom01 ]
分区:内容:[分区:内容:Tom03 ]
分区:内容:[分区:1内容:Tom05 ]
分区:内容:[分区:1内容:Tom07 ]
分区:内容:[分区:2内容:Tom09 ]
分区:内容:[分区:2内容:Tom11 ]
分区:1内容:[分区:内容:Tom02 ]
分区:1内容:[分区:内容:Tom04 ]
分区:1内容:[分区:1内容:Tom06 ]
分区:1内容:[分区:1内容:Tom08 ]
分区:1内容:[分区:2内容:Tom10 ]
分区:1内容:[分区:2内容:Tom12 ]

下图说明了三种coalesce的情况:

分区:改变RDD分区数

repartition(int n)=合并(int n,true)

partitionBy:通过自定义分区器更改RDD分区数
1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
JavaPairRDD < 整数,字符串 > partitionByRDD = nameRDD.partitionBy(new Partitioner(){
              
    私有静态最终长serialVersionUID = 1 L;
    
    //分区数2
    @Override
    public int numPartitions(){
        返回 2 ;
    }
    //分区逻辑
    @Override
    public int getPartition(Object obj){
        int i =(int)obj;
        如果(i%2 == ){
            返回 ;
        } 其他 {
            返回 1 ;
        }
    }
});
``` 
 
##### glom:把分区中的元素封装到数组中
```斯卡拉
VAL RDD = sc.parallelize(1至10,2) 
/ **
 * rdd有两个分区
 * partition0分区的所有元素封装到一个副本
 * partition1分区的所有元素封装到一个副本
 * /
val glomRDD = rdd.glom()
glomRDD.foreach(x => {
  println(“ ============”)
  x.foreach(println)
println(“ ============”)
})
println(glomRDD.count())
结果:
============
1个
2
3
4
5
============
============
6
7
8
9
10
============
2
randomSplit:细分RDD
1个
2
3
4
5
6
7
8
9
10
11
12
13
/ **
 * randomSplit:
 *根据预期的Array中每个元素的权重将rdd分割成Array.size个RDD
 *分割后的RDD中元素数量由权重来决定,数据量不大时不一定准确
 * /
val rdd = sc.parallelize(1到10)
rdd.randomSplit(阵列(0.1,0.2,0.3,0.4))。的foreach(X => {的println(x.count)})
理论结果:
1个
2
3
4
实际结果不一定准确
压缩

与zip有关的3个算子如下图所示:

算子案例

WordCount-Java版

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65岁
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/ **
 *文件中的数据:
 *星火核心
 *火花流
 * Spark SQL
 * @作者根
 * /
公共 类 WordCount {
     
     公共 静态 void 主(String [] args) {
         / *
          * SparkConf对象主要用于设置Spark运行时的环境参数:
          * 1.运行模式
          * 2.申请名称
          * 3.运行时的资源需求
          * /
         SparkConf conf = 新的 SparkConf();
          conf.setMaster(“ local”).setAppName(“ WordCount”);
         / *
          * SparkContext是Spark运行的一部分,是集成Spark占用的唯一通道
          * /
         JavaSparkContext jsc = 新的 JavaSparkContext(conf);
         
         字符串路径= “ cs”;
         JavaRDD <String> rdd = jsc.textFile(path);
         
         // =================单词计数开始=================
         flatMapRDD.mapToPair(new PairFunction <String,String,Integer>(){
              / **
               *
               * /
              私有 静态 最终 长 serialVersionUID = 1L ;
              @Override
              公共 Tuple2 <String,Integer> 调用(字符串字)
引发异常{
                  返回 新的 Tuple2 <String,Integer>(word,1);
              }
         })。reduceByKey(new Function2 <Integer,Integer,Integer>(){
              
              / **
               *
               * /
              私有 静态 最终 长 serialVersionUID = 1L ;
              @Override
              公用 Integer 调用(Integer v1,Integer v2)
引发异常{
                  返回 v1 + v2;
              }
         })。mapToPair(new PairFunction <Tuple2 <String,Integer>,
整数,字符串>(){
              / **
               *
               * /
              私有 静态 最终 长 serialVersionUID = 1L ;
              @Override
              公共 Tuple2 <Integer,String> 调用(
Tuple2 <String,Integer> tuple)引发异常{
                  返回 新的 Tuple2 <Integer,String>(tuple._2,tuple._1);
              }
         })。sortByKey(false)// fasle:降序
         .mapToPair(new PairFunction <Tuple2 <Integer,String>,
字符串,整数>(){
              / **
               *
               * /
              私有 静态 最终 长 serialVersionUID = 1L ;
              @Override
              公共 Tuple2 <String,Integer> 调用(
Tuple2 <Integer,String> tuple)引发异常{
                  返回 新的 Tuple2 <String,Integer>(tuple._2,tuple._1);
              }
         })。foreach(new VoidFunction <Tuple2 <String,Integer >>(){
              
              / **
               *
               * /
              私有 静态 最终 长 serialVersionUID = 1L ;
              @Override
              公共 无效 调用(Tuple2 <String,Integer>元组)
引发异常{
                  System.out.println(元组);
              }
         });;
         // ================字数结尾==================
         jsc.stop();
     }
}
结果:
(火花,3)
(SQL,1)
(流式传输1)
(核心1)

过滤掉出现次数最多的数据-Scala版

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/ **
 *文件中的数据:
 *你好Java
 *你好Java
 *你好Java
 *你好Java
 *你好Java
 *你好哈杜普
 *你好哈杜普
 *你好哈杜普
 *你好蜂巢
 *你好蜂巢
 * 你好,世界
 *你好火花
 * @作者根
 * /
对象 FilterMost {
  def main(args: Array [ String ]): Unit = {
    val conf = new SparkConf()
        .setMaster(“ local”)
        .setAppName(“ FilterMost”)
    val sc = 新的 SparkContext(conf)
   
    val rdd:RDD [ 字符串 ] = sc.textFile(“ test”)
    val sampleRDD:RDD [ 字符串 ] = rdd.sample(false,0.9)
    val结果= sampleRDD
      .map {x =>(x.split(“”)(1),1)}
      .reduceByKey(_ + _)
      .map {x => {(x._2,x._1)}}
      .sortByKey(false)
      。第一()
      ._2
    rdd
      .filter {(!_。contains(result))}
      .foreach(println)
     
    sc.stop();
  }
}
结果:
你好哈杜普
你好哈杜普
你好哈杜普
你好,蜂巢
你好,蜂巢
你好,世界
你好火花

统计每个页面的UV

部分数据如下:
日期更改内的用户ID pageID模块用户事件
2017-05-13 1494643577030 null 54 Kafka视图
2017-05-13 1494643577031 8 70 Kafka注册
2017-05-13 1494643577031 9 12 Storm View
2017-05-13 1494643577031 9 1 Scala视图
2017-05-13 1494643577032 7 73 Scala注册
2017-05-13 1494643577032 16 23 Storm注册

标量:

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
对象 CountUV  {
  def main(args: Array [ String ]): Unit = {
    val conf = new SparkConf()
    conf.setMaster(“本地”)
    conf.setAppName(“ CountUV”)
   
    val sc = 新的 SparkContext(conf)
   
    val rdd = sc.textFile(“ userLog”)
    val结果= rdd.filter(!_。split(“ \ t”)(2).contains(“ null”))
    .map(x => {
      (x.split(“ \ t”)(3),x.split(“ \ t”)(2))
    })
    .distinct()。countByKey()
   
    result.foreach(x => {
      println(“ PageId:” + x._1 + “ \ tUV:” + x._2)
    })
   
    sc.stop();
  }
}

Java代码:

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
公共 课程 CountUV {
     
     公共 静态 void 主(String [] args) {
         SparkConf sparkConf = 新的 SparkConf()
.setMaster(“ local”)
.setAppName(“ CountUV”);
         最终的 JavaSparkContext jsc = 新的 JavaSparkContext(sparkConf);
         
         JavaRDD <String> rdd = jsc.textFile(“ userLog”);
         
         JavaRDD <String> filteredRDD =
rdd.filter(new Function <String,Boolean>(){
              / **
               *
               * /
              私有 静态 最终 长 serialVersionUID = 1L ;
              @Override
              公共布尔调用(字符串v1) 抛出异常 {
                  退货!“ null” .equals(v1.split(“ \ t”)[ 2 ]);
              }
         });
         
         JavaPairRDD <String,String> pairRDD =
filterRDD.mapToPair (new PairFunction <String,String,String>(){
              / **
               *
               * /
              私有 静态 最终 长 serialVersionUID = 1L ;
              @Override
              公共 Tuple2 <String,String> 调用(String t)
引发异常{
                  String [] splits = t.split(“ \ t”);
                 返回 新的 Tuple2 <String,String>(splits [ 3 ],splits [ 2 ]);
              }
         });
         
         JavaPairRDD <String,String> distantRDD = pairRDD.distinct();
         
         Map <String,Object> resultMap = distantRDD.countByKey();
         
         对于(Entry <String,Object> entry:resultMap.entrySet()){
              System.out.println(“ pageId:” + entry.getKey()+
“ UV:” + entry.getValue());
         }
         
         jsc.stop();
     }
}
部分结果:
pageId:45 UV:20
pageId:98 UV:20
pageId:34 UV:18
pageId:67 UV:20
pageId:93 UV:20

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31509949/viewspace-3152658/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
管理员

注册时间:2018-03-30

  • 博文量
    2383
  • 访问量
    984528