spark快速开发之scala基础

246 阅读6分钟

写在前面

面向java开发者。实际上,具有java基础学习scala是很容易。java也可以开发spark,并不比scala开发的spark程序慢。但学习scala可有助于更快更好的理解spark。比如spark的很多算子group,filter之类的,全都是scala语言本身所具备的功能。再比如,想做一个更高级别的spark开发者,势必需要了解spark源码。哪怕不需要通读,但也需要了解scala语言。

快速入门的意思先具备一个宏观上的系统而整体的把控,然后再到这个框架上去把血肉丰满。从阅读源码的角度来说,作为一个java开发者,在数据类型和容器,控制语句等方面,哪怕不会写,至少能大致读懂。但涉及到更高层次的高阶函数,就很头痛了。

比如list。只会讲声明,增删查改以及循环。就能满足大多数情况下的开发。至于其它的功能,通过查看文档,或者源码,就可以搞懂。涉及到像增这一块,比如添加一个元素,list有【++: ++ +: :+ :: ::: :\】等很多功能。但本文只涉及最简单的东西。总之,这是一个简易版的入门。后续的学习不能停止

1. 数据类型与容器

数据类型

scala数据类型与java基本类似。scala在面向对象方面,比java列我彻底。java有8种基本数据类型,在scala里面全是对象。

Byte8位有符号补码整数。数值区间为 -128 到 127
Short 16位有符号补码整数。数值区间为 -32768 到 32767
Int32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Long 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
Float 32位IEEE754单精度浮点数
Double 64位IEEE754单精度浮点数
Char 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
Boolean true或false

其它常见数据类型:

Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Null null 或空引用
Nothing Nothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。
Any Any是所有其他类的超类
AnyRef AnyRef类是Scala里所有引用类(reference class)的基类

 变量

在 Scala 中,使用关键词 "var" 声明变量,使用关键词 "val" 声明常量。

声明变量实例如下:

var myVar : String = "Foo"
var myVar : String = "Too"

以上定义了变量 myVar,我们可以修改它。

声明常量实例如下:

val myVal : String = "Foo"

以上定义了常量 myVal,它是不能修改的。如果程序尝试修改常量 myVal 的值,程序将会在编译时报错。

 

变量声明不一定需要初始值,以下也是正确的:

var myVar :Int;
val myVal :String;

变量类型引用

在 Scala 中声明变量和常量不一定要指明数据类型,在没有指明数据类型的情况下,其数据类型是通过变量或常量的初始值推断出来的。

所以,如果在没有指明数据类型的情况下声明变量或常量必须要给出其初始值,否则将会报错。

var myVar = 10;
val myVal = "Hello, Scala!";

以上实例中,myVar 会被推断为 Int 类型,myVal 会被推断为 String 类型。


Scala 多个变量声明

Scala 支持多个变量的声明:

val xmax, ymax = 100  // xmax, ymax都声明为100


集合

list
//定义
    var list = List("spark","hadoop","storm")
    var nums = List("sdf","spark")
    val empty : List[Nothing] = List()
    
    val list2 = list.+:("sdf")//在头部添加元素
    println(list2)
    val list3 = list.++(nums)//合并两个集合
    println(list3)
    val list4 = list.:+("sdf")//在尾部添加元素
    println(list4)
    
    val item = list take 3 //取前几个元素
    val head = list.head//取第一个元素
    val last = list.last//取最后一个元素
    
    list.updated(1, "mr")//更新
    
    //循环
    list.foreach(println)
    list.map(println)

数组

大体与list相当

    //array
    val array : Array[Any] = Array("spark","hadoop","storm")
    println(array)
    val array2 : Array[String] = Array("spark2","hadoop2")
    array.foreach(println)
    println(array(0))//取值
    println(array.apply(0))//取值
    val array3 = array.++:(array2)
    println("================")
    array3.foreach(println)//循环
    val array4 = array.+:("spark").:+("hadoop")//加值
    println("================")
    array4.foreach(println)
    
    val array5 = array.++(array2)
    
    array5.foreach(print)
    
    //seq
    val seq = Seq("hadoop","spark")
    println(seq)

map

Map 有两种类型,可变与不可变,区别在于可变对象可以修改它,而不可变对象不可以。

默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map

    var map = Map("spark"->1,"hadoop"->"1")
    val map2 = Map("spark2"->1,"hadoop2"->"1")
    val map3 = map.+(("storm"->1))//添加一个元素
    map += ("storm"->1)//添加一个元素
    val map4 = map.++(map2)//合并两个集合
    println(map4)
    map.contains("spark")//判断一个元素是否存在
    map.isEmpty//是否为空
    //得到key集合
    val keys2 : Iterable[String] = map.keys
    val keys : Set[String] = map.keySet
    val iter : Iterator[String] = map.keysIterator

 

set

Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的。

Scala 集合分为可变的和不可变的集合。

默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。

   val set = Set("spark","spark","hadoop")
    set += "storm" //异常
    val mutableSet : Set[String] = Set("spark","spark","hadoop")
    mutableSet += "hive"
    println(mutableSet)
    mutableSet.add("scala")
    println(mutableSet)
    mutableSet.remove("scala")
    println(mutableSet)
    mutableSet -= "hive"
    println(mutableSet)

2 控制流程

判断结构

大体与java相当。scala没有三元表达式。

    val num = if(1>0) 1 else 0 //相当于匿名函数
    println(num)
    
    var num2 = 0
    if(1>0) num2 = 1 else num2 = 0
    
    println(num2)

 

选择结构

match。与java的stiwch相当。但scala的match强大很多。

 

  1. 通配符匹配(Wildcard Pattern Matching )
  2. 常量匹配 (Constant Pattern Matching )
  3. 变量匹配(Variable Pattern Matching )
  4. 构造函数匹配(Constructor Pattern Matching )
  5. 集合类型匹配(Sequence Pattern Matching )
  6. 元祖类型匹配(Tuple Pattern Matching )
  7. 类型匹配(Typed Pattern Matching )

 

        // constant patterns
        case 0 => "zero"
        case true => "true"
        case "hello" => "you said 'hello'"
        case Nil => "an empty List"
        // sequence patterns
        case List(0, _, _) => "a three-element list with 0 as the first element"
        case List(1, _*) => "a list beginning with 1, having any number of elements"
        case Vector(1, _*) => "a vector starting with 1, having any number of elements"
        // tuples
        case (a, b) => s"got $a and $b"
        case (a, b, c) => s"got $a, $b, and $c"
        // constructor patterns
        case Person(first, "Alexander") => s"found an Alexander, first name = $first"
        case Dog("Suka") => "found a dog named Suka"
        // typed patterns
        case s: String => s"you gave me this string: $s"
        case i: Int => s"thanks for the int: $i"
        case f: Float => s"thanks for the float: $f"
        case a: Array[Int] => s"an array of int: ${a.mkString(",")}"
        case as: Array[String] => s"an array of strings: ${as.mkString(",")}"
        case d: Dog => s"dog: ${d.name}"
        case list: List[_] => s"thanks for the List: $list"
        case m: Map[_, _] => m.toString
        // the default wildcard pattern
        case _ => "Unknown"

 

循环结构

while 

do while

与java相同。

for 可以多重循环,循环过滤。返回值。

    val list = List("3423")
    for(t <- list){
      println(t)
    }
    
    for(i <- 1 to 10){//包含10
      println(i)
    }
    
    for(i <- 1 until 10){//不包含10
      println(i)
    }
    println("===================")
    for(i <- 1 to 10;if i> 5){//添加过滤条件
      println(i)
    }
    println("===================")
    for(i <- 1 to 10;j <- 1 to 10){
      println(i +" " + j)
    }
    println("===================")
    
     for (i <- 1 to 5) yield i * 2 
    
    var result = for(t <- list) yield t //result = list
    var result2 = for(t <- list)  yield t + "10"
    result.foreach(println)

 

异常控制

   try{
      
    }catch{
      case ex : NullPointerException => ex.printStackTrace()
      case _: Exception => ""
    }

 

break  continue

scala没有这两个关键字。但是scala提供了Breaks类来达到相同的效果。

 def continue() {
    for (i <- 1 to 10) {
      Breaks.breakable({
        if (i == 5) {
          Breaks.break()
        }
        println(i)
      })
    }
    println("break")
  }

执行结果:

1
2
3
4
6
7
8
9
10
break

 def break() {
    Breaks.breakable({
      for (i <- 1 to 10) {
        if (i == 5) {
          Breaks.break()
        }
        println(i)
      }
    })
    println("break")
  }

执行结果:

1
2
3
4
break