Scala 与spark 7.23

 

知识点:

 

  • @transient

如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。

换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。

这对于需要被临时保存的缓存数据而言是合理的。

例如:

@transient val sparkContext: SparkContext,

 

  • Scala多行字符串 之stripMargin方法

https://www.jianshu.com/p/08986dbab540

如:

    var sql =

    s"""

       | select

       | case when app_id is null then 0 else app_id end as app_id,

       | case when app_package is null then '-' else app_package end as app_package,

       | case when first_type is null then 0 else first_type end as first_type,

       | case when second_type is null then 0 else second_type end as second_type

       | from cpd_reco.dm_cpd_recommend_app_info where day='${yesterday}'

      """.stripMargin

 

  • Logger打印日志

https://blog.csdn.net/zalan01408980/article/details/79653386

 

  • scala 时间格式转换(String、Long、Date)

1、时间字符类型转Date类型

import java.text.SimpleDateFormat

val time = "2017-12-18 00:01:56"

val newtime :Date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(time)

println(newtime)

//output:Mon Dec 18 00:01:56 CST 2017

2、Long类型转字符类型

val time:Long= 1513839667//秒

val newtime :String = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time*1000)

println(newtime)

//output:2017-12-21 15:01:07

3、时间字符类型转Long类型

val time = "2017-12-18 00:01:56"

val newtime :Long= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(time).getTime

println(newtime)  //output:1513526516000

 

  • Scala 字符串插值器s,f 和 raw.

Scala 提供了三种创新的字符串插值方法:s,f 和 raw.

 

s 字符串插值器

在任何字符串前加上s,就可以直接在串中使用变量了。

val name="James"

println(s"Hello,$name")//Hello,James 此例中,$name嵌套在一个将被s字符串插值器处理的字符串中。插值器知道在这个字符串的这个地方应该插入这个name变量的值,以使输出字符串为Hello,James。使用s插值器,在这个字符串中可以使用任何在处理范围内的名字。

字符串插值器也可以处理任意的表达式。例如:

 

println(s"1+1=${1+1}") 将会输出字符串1+1=2。任何表达式都可以嵌入到${}中。

f 插值器

在任何字符串字面前加上 f,就可以生成简单的格式化串,功能相似于其他语言中的 printf 函数。当使用 f 插值器的时候,所有的变量引用都应当后跟一个printf-style格式的字符串,如%d。

val height=1.9d

val name="James"

println(f"$name%s is $height%2.2f meters tall")//James is 1.90 meters tall f 插值器是类型安全的。如果试图向只支持 int 的格式化串传入一个double 值,编译器则会报错。例如:

val height:Double=1.9d

scala>f"$height%4d"

:9: error: type mismatch;

found : Double

required: Int

f"$height%4d"

^ f 插值器利用了java中的字符串数据格式。这种以%开头的格式在 [Formatter javadoc] 中有相关概述。如果在具体变量后没有%,则格式化程序默认使用 %s(串型)格式。

 

raw 插值器

除了对字面值中的字符不做编码外,raw 插值器与 s 插值器在功能上是相同的。如下是个被处理过的字符串:

scala>s"a\nb"

res0:String=

a

b 这里,s 插值器用回车代替了\n。而raw插值器却不会如此处理。

scala>raw"a\nb"

res1:String=a\nb 当不想输入\n被转换为回车的时候,raw 插值器是非常实用的。

除了以上三种字符串插值器外,使用者可以自定义插值器。

 

  • SQLContext/HiveContext/SparkSession使用和区别

 

  1. SparkContext其实是连接集群以及获取spark配置文件信息,然后运行在集群中。
  2. SQLContext:spark处理结构化数据的入口。允许创建DataFrame以及sql查询。如果不使用hive的功能的话,可以直接使用SQLContext对象来执行,如果要使用hive中的函数和hive的功能,要读取hive的配置的话,就需要创建HiveContext
  3. HiveContext:spark sql执行引擎,集成hive数据,读取在classpath的 hive-site.xml配置文件配置Hive
  4. 对于spark1.x,SQLContext和HiveContext的使用是需要区分的。
  5. 对于spark2.x,统一使用SparkSession。如果是使用spark2以上的版本,建议适用sparksession。sparksession == hivecontext+sqlcontext

 

SQLContext和HiveContext区别与联系为:

SQLContext现在只支持SQL语法解析器(SQL-92语法)

HiveContext现在支持SQL语法解析器和HiveSQL语法解析器,默认为HiveSQL语法解析器,用户可以通过配置切换成SQL语法解析器,来运行HiveSQL不支持的语法。

使用HiveContext可以使用Hive的UDF,读写Hive表数据等Hive操作。SQLContext不可以对Hive进行操作。

Spark SQL未来的版本会不断丰富SQLContext的功能,做到SQLContext和HiveContext的功能容和,最终可能两者会统一成一个Context

HiveContext包装了Hive的依赖包,把HiveContext单独拿出来,可以在部署基本的Spark的时候就不需要Hive的依赖包,需要使用HiveContext时再把Hive的各种依赖包加进来。

 

SQL的解析器可以通过配置spark.sql.dialect参数进行配置。在SQLContext中只能使用Spark SQL提供的”sql“解析器。在HiveContext中默认解析器为”hiveql“,也支持”sql“解析器。

 

Spark Application可以使用SQLContext的sql()方法执行SQL查询操作,sql()方法返回的查询结果为DataFrame格式。代码如下:

Scala:

val sqlContext = ...  // An existing SQLContext

val df = sqlContext.sql("SELECT * FROM table")

 

  • Spark函数之collect、toArray和collectAsMap

collect、toArray:将RDD转换为Scala的数组。

collectAsMap:与collect、toArray相似。collectAsMap将key-value型的RDD转换为Scala的map。

注意:map中如果有相同的key,其value只保存最后一个值。

 

  • spark RDD算子(一) parallelize,makeRDD,textFile

原文链接:https://blog.csdn.net/T1DMzks/java/article/details/70189509

 

parallelize

调用SparkContext 的 parallelize(),将一个存在的集合,变成一个RDD,这种方式试用于学习spark和做一些spark的测试

scala版本

def parallelize[T](seq: Seq[T], numSlices: Int = defaultParallelism)(implicit arg0: ClassTag[T]): RDD[T]

- 第一个参数一是一个 Seq集合

- 第二个参数是分区数

- 返回的是RDD[T]

scala> sc.parallelize(List("shenzhen", "is a beautiful city"))

res1: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[1] at parallelize at :22

java版本

def parallelize[T](list : java.util.List[T], numSlices : scala.Int) : org.apache.spark.api.java.JavaRDD[T] = { /* compiled code */ }

- 第一个参数是一个List集合

- 第二个参数是一个分区,可以默认

- 返回的是一个JavaRDD[T]

java版本只能接收List的集合

JavaRDD javaStringRDD = sc.parallelize(Arrays.asList("shenzhen", "is a beautiful city"));

 

makeRDD

只有scala版本的才有makeRDD

def makeRDD[T](seq : scala.Seq[T], numSlices : scala.Int = { /* compiled code */ })

跟parallelize类似

sc.makeRDD(List("shenzhen", "is a beautiful city"))

 

textFile

调用SparkContext.textFile()方法,从外部存储中读取数据来创建 RDD

例如在我本地F:\dataexample\wordcount\input下有个sample.txt文件,文件随便写了点内容,我需要将里面的内容读取出来创建RDD

scala版本

var lines = sc.textFile("F:\\dataexample\\wordcount\\input")

java版本

 JavaRDD lines = sc.textFile("F:\\dataexample\\wordcount\\input");

注: textFile支持分区,支持模式匹配,例如把F:\dataexample\wordcount\目录下inp开头的给转换成RDD

var lines = sc.textFile("F:\\dataexample\\wordcount\\inp*")

多个路径可以使用逗号分隔,例如

var lines = sc.textFile("dir1,dir2",3)

 

  • Spark 的 agrregate 作用

https://www.cnblogs.com/chorm590/p/spark_201904201159.html

 

  • spark中的combineByKey函数的用法

https://www.cnblogs.com/Gxiaobai/p/10056482.html

https://blog.csdn.net/huangyinzhao/article/details/80341763

通过阅读上面的讲解,发现其实在combineByKey这个函数中传入的处理数据的函数,都是只是对key-value键值对数据中的value进行处理,定义的那些函数都并不处理key。所以像第一个链接中的 v: (String, Int)) => (v: (String, Int) 这个createCombiner函数,都是除去了key之后定义的value 的数据类型(String, Int)。可以看到后面的其他函数也是这样的。

所以acc: (String, Int), v: (String, Int)) => (v._1+":"+acc._1,acc._2+v._2)这里的v._1和acc._1都是指经过map函数转化之后的得到的元组value中的第一个。

 

  • 【Scala】 groupBy、grouped 方法详解

https://www.it610.com/article/1282391701956083712.htm

groupby函数的输出结果是自己设置的key:seq。

这里的seq是原来的序列数据中的满足key 的各项。也就是,如果不对原来序列中的各项进行转换操作的话,key后面的list就是和原来数据中的项是一样的。只是把各项整合在一个list中的,然后变成了一个key-value键值对的形式。

 

  • Spark中 groupBy() 与groupByKey()的区别

首先根据两个方法的名字,我们大概可以了解到:

 

       两个方法的差异就在于有没有 key这个单词,所以说:groupBy()方法是根据用户自定义的情况进行分组,而groupByKey()则是根据key值进行分组的,也就是说,进行groupByKey()方法的数据本身就是一种key-value类型的,并且数据的分组方式就是根据这个key值相同的进行分组的

 

      那么groupBy()分组的方法呢?就是工具groupBy()传入的方法返回的值进行分组

 

所以,groupByKey的输出结果和上面写的groupBy的结果会是一样的形式。

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(spark)