Scala 编程基础
为什么要了解Scala编程基础,因为在Spark开发中,经常碰到Scala语法,理解这些语法便于顺利
Scala 类
Scala 范型
class Person[T](name:T)
class Student[T,S](name:T, age:S) extends Person(name)
object GenericTypeTest {
def main(args:Array[String]): Unit = {
val stu = new Student[String,Int]("张三",30)
print(stu.name)
}
}
类型范围界定 (符号 <:)
类型变量界定是指在范型的基础上,缩小范型的具体类型
class GenericTypeTest2 {
// 泛型 T 要继承Comparable才能具备compareTo 方法
def compare[T <: Comparable[T]](first:T, second:T) = {
if (first.compareTo(second) > 0)
first
else
second
}
}
object GenericTypeTest2 {
def main(args:Array[String]): Unit = {
val genericDemo = new GenericTypeTest2
genericDemo.compare("A", "B")
}
}
视图界定(符号<%)
类型变量界定是建立在类继承层次结构的基础上,但有时候这种限定不能满足实际要求,比如:
object GenericTypeTest3 {
def main(args: Array[String]): Unit = {
// 这是合法的语句
val s= Student("john","170")
// 下面这条语句不合法,这是因为 ,Int 类型没有实现 Comparable 接口
val s2= Student("john",170)
}
}
为了能够支持这种跨类型层次结构的场景,可以使用视图界定来实现,原理是通过隐式转换来实现。
case class Student[T,S <% Comparable[S]](name:T, age:S)
object GenericTypeTest3 {
def main(args: Array[String]): Unit = {
val s= Student("john","170")
val s2= Student("john",170) // Int 类型 的变量经过 隐式 转换成了 R ichInt 类型, R ichInt 类型是实现了 C omparable 接口的
}
}
上界(<:)和下界(>:)
- 上界:要求对象必须是某一个对象的子类,因为子类会继承父类的属性和方法,所以父类的方法和属性都能用,实例见compare方法;
- 下界:要求对象A必须是某一个对象B的父类,B是一个具体类型,要把B赋值给A类型
// 下界
def add[A >: B](list: collection.mutable.Set[A], elem: B): collection.mutable.Set[A] = {
list.add(elem)
list
}
Scala常用特殊符号
特征符号 | 解释 | 样例 |
---|---|---|
=> | 创建一个匿名函数 (形参列表) => {函数体},spark中函数也是一个对象可以赋值给一个变量 | val aaa =b; val bbb = a |
<- | 集合遍历 for (aa <- list) | |
++= | 字符串拼接(等同于+=) | |
::: | 三个冒号 表示List的连接操作,只适用list 类似于Java中的 list1.addAll(list2) | |
:: | 两个冒号运算符表示普通元素与list的连接操作 类似于Java中的list1.add(A) | |
++ | 连接两个Seq,适用于列表、集合、字符串、Map | |
:+ | 方法:用于在列表尾部追加元素 | |
+: | 方法:用于在列表头部追加元素 记住冒号永远靠近集合类型 | |
-> | 构造元组, 元组是不同类型的值聚集线程的列表 通过将多个值使用小括号括起来,即表示元组scala中元组与数组区别:数组中元素 数据类型必须一样,但是元组数据类型可以不同。 | val one = 1; val two = 2; val three = one -> two; println(three) // 构造二元元组 |
+= | 为可变数组添加元素,为map添加新的值 | |
-= | 为可变数组减去元素,为map移除相应的值 | |
:_* | 作为一个整体,告诉编译器将某个参数当做序列处理 | df.select(df("value") +: (0 until 7).map(i => df("value")(i).alias(s"_$i")):_*) //将df:DataFrame(Array[String])中数组每个元素转换成列 |
_(下划线) | 指代集合中的每一个元素 | val lst = List(1,2,3,4,5);val lstFilter = lst.filter(_ > 3) |
_N | 访问元组第N个元素 | println(three._2) |
使用模式匹配可以用来获取元组的组员
val m = Map(1 -> 2,2 -> 4)
for ((k,_) <- m) println(k) //如果不需要所有部件, 则在不需要的部件使用_; 本例只取key,因此在value处用_
成员变量而非局部变量添加默认值
var s:Int=_
def main(args: Array[String]): Unit = {
println(s)
}
def main(args: Array[String]): Unit = {
val s = sum(1 to 5:_*) //把1 to 5当作一个序列处理
println(s)
}
def sum(args: Int*) : Int = {
var result = 0 ;
for(s2 <- args) {
result += s2 ;
}
result ;
}
Scala API
SeqLike.diff(other:SeqLike)
scala> val a = Seq(1,2,3,3)
a: Seq[Int] = List(1, 2, 3, 3)
scala> val b = Seq(1,3)
b: Seq[Int] = List(1, 3)
scala> a.toArray.diff(b)
res5: Array[Int] = Array(2, 3)
SeqLike.sort
SeqLike.sorted
/** Sorts this $coll according to an Ordering.
*
* The sort is stable. That is, elements that are equal (as determined by
* `lt`) appear in the same order in the sorted sequence as in the original.
*
* @see [[scala.math.Ordering]]
*
* @param ord the ordering to be used to compare elements.
* @return a $coll consisting of the elements of this $coll
* sorted according to the ordering `ord`.
*/
def sorted[B >: A](implicit ord: Ordering[B]): Repr = {
val len = this.length
val arr = new ArraySeq[A](len)
var i = 0
for (x <- this.seq) {
arr(i) = x
i += 1
}
java.util.Arrays.sort(arr.array, ord.asInstanceOf[Ordering[Object]])
val b = newBuilder
b.sizeHint(len)
for (x <- arr) b += x
b.result
}
SeqLike.sortBy()
def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Repr = sorted(ord on f)
SeqLike.sortWith
def sortWith(lt: (A, A) => Boolean): Repr = sorted(Ordering fromLessThan lt)
Scala 编码规范
https://github.com/databricks/scala-style-guide/blob/master/README-ZH.md