Scala基础

Scala基础

1、介绍

Scala是spark和kafka采用的编程语言,本质上是对java语言进行脚本化处理,使得开发效率更高。Scala的代码编写起来非常简洁,但并不简单,主要是很多语法比较诡异,对于刚刚接触到scala的人员来讲,往往有些摸不到头脑。

2、scala使用

打开scala的shell命令行窗口,输入1 + 1,可以直接进行求值运算。scala shell采用REPL方式进行交互,即read->evalute->print->loop。进入如下环境,运行效果如下图所示:

cmd>scala.bat
scala> 1 + 1

1538193648630

2.1 查看帮助

$scala>:help

1538193747272

2.2 退出

$scala>:quit

2.3 常量和变量

scala的量分为常量和变量,var是变量,可以重新赋值,val是常量,不可以重新复制。

// 变量
val x =10
// 错误,不能重新赋值
x = 20

var x = 10
// 正确
x = 20

2.4 类型推断与自动补全

val x = 100
val x:Int = 100
// tab键自动提示
x.<tab>

2.5 定义函数

递归函数必须显式定义函数,因为无法进行类型推荐。

// 参数必须定义类型,返回值可以不写,自动推断出来
def add(a:Int,b:Int) = {
    a + b
}

// 显式定义返回值类型
def add(a:Int,b:Int):Int = {
    a + b
}

// 递归实现阶乘
def frac(n:Int):Int = {
	if(n == 1) 1 else n * frac(n - 1)
}

2.6 to和until

to和until都可以定义Range集合,to是闭区间,until是半闭半开区间。

// 1 .. 10
1 to 10
1.to(10)

// 1 .. 9
1 until 10
1.until(10)

2.7 字符串

// 取交集,lo
"hello".intersect("world")

2.8 BigInt

var b = BigInt(999999999)
b * b * b * b

2.9 ++/--

scala没有++或--操作,可以使用+=或-=,这些也都是方法。

var x = 1 
// x ++ 
x += 1
x.+=(1)

// x --
x -=1 
x.-=(1)

2.10 sqrt与pow

开方函数和幂函数都在math包下,因此需要导入才能使用:

import scala.math._
// 4开方=2.0
sqrt(4)
// 2的立方=8
pow(2,3)

2.11 表达式的值

scala的每个表达式或者代码块都有值,最后一行语句的值就是表达式的值。

val x = 2
// y = 1
val y = if (x < 1) -1 else 1 

2.12 apply方法

scala为很多类提供了apply方法,可以方便进行各种对象的创建和元素的获取,apply方法名成通常可以省略,因此会让方法调用显得有些奇怪。

// 省略apply方法名
val arr = Array[Int](1,2,3)
val arr = Array[Int].apply(1,2,3) ;

// 省略了apply方法
"hello"(0)
"hello".apply(0)

2.13 粘贴模式

在scala shell可以使用粘贴模式来贴入大量代码:

# 进入粘贴模式的命令
$scala>:paste

# ctrl + d退出粘贴模式

2.14 读取控制台输入

// 字符串为控制台提示符
val name = readLine("请输入用户名:") ;
println(name) ;

运行结果如图:

1538203922670

2.15 循环

2.15.1 while

while循环同java相似,都是用boolean类型表示进行控制。

  • 输出1~10

    var n = 1
    while(n < 11){
    	println(n)
        n += 1
    }
    
  • 输出99表格

    var row = 1
    while( row <= 9 ){
    	var col = 1 
        while( col <= 9){
        	printf("%dx%d=%d	" ,col,row , (col * row))
        }
        println()
    }
    
2.15.2 for
  • 输出1~10

    for(i <- 1 to 10){
    	println(i)
    }
    
  • 输出99表格

    for(r <- 1 to 10){
        for(c <- 1 to r){
            printf("%dx%d=%d	" ,c,r , (c * r))
        }
        println()
    }
    

    运行结果如下:

    1538204862072

  • 带守卫条件的循环

    for(i <- 1 to 3 ; j <- 4 to 6 if j != 5){
      printf("%d : %d
    " , i , j )
    }
    

    如果j不等5的条件下,和i进行组合计算:

    1538212280072

2.16 break

scala没有break语句,需要导入特定的函数来执行:

// 导入break函数
import scala.util.control.Breaks.break

for(i <- 1 to 10){
  if(i % 3 == 0){
    break 
  }
}

2.17 yield产生新集合

// 每个元素 * 2,组成新集合
for(i <- 1 to 5) yield i * 2

执行结果如下:

1538212654302

2.18 函数

  • 定义函数

    // 递归函数必须显式定义返回值类型
    def fac(n:Int) : Int = {
    	var result = 0 
        for(i <- (1 to n)){
        	result *= i
        }
        //最后一条语句是返回值
        result
    }
    
  • 参数默认值和带名参数

    // 定义修饰串函数
    def decorate(prefix:String="{{{" , str:String  , suffix:String="}}}") = {
    	prefix + str + suffix 
    }
    //调用函数
    decorate("<<<" , "hello" , ">>>")
    // 输出结果
    "<<<hello>>>"
    // 使用带名参数向特定参数传值
    decorate(str="world" , suffix="}}}")
    
  • 变长参数

    变长参数等价于java中的可变参数,即参数的类型个数可以不固定。

    // 定义可变参数
    def add(x:Int*) = {
        var sum = 0 
        for(i <- x){
        	sum += i 
        }
        sum
    }
    
    // 传递多个参数
    add(1,2,3)
    
    // 使用_*转换成数字序列
    add(1 to 10 :_*)
    
  • 过程

    scala中将不带“=”的函数称之为过程,本质上和函数没有区别。

    // 没有=号
    def sayHi() {
        println("hello world!")
    }
    

2.19 lazy

lazy是延迟计算,即表达式不会立即求值,而是使用lazy字样作为占位符,等真正用到的时候再进行计算。spark的广播变量中使用该中方式进行的实现。

// lazy变量,不会出错
lazy var x = 1 / 0

// 出错
x 

2.20 定义数组

  • 一维数组

    # 定义一个一维数组,长度为5个元素。
    val arr = new Array[Int](5)
    
    # 定义一个一维数组,内部调用apply方法
    var arr = Array[Int](5)
    var arr = Array[Int](1,2,3,4,5)
    
  • 二维数组

    // 定义二维数组
    var arrr = new Array[Array[Int]](3)
    // 赋值
    arrr[0] = Array[Int](1,2,3)
    
    # 三行四列数组
    val arr = Array.ofDim[Int](3,4)
    # 第一行第二列为2
    arr(0)(1) = 2
    

2.21 ArrayBuffer

数组缓冲区是可变数组,位于scala.collection.mutable包下,使用时需要进行导入。scala使用符号定义的方法有一定规律性:

    当个符号的方法通常意味着操纵一个元素,如:

    val arr = ArrayBuffer[Int](1,2,3)
    arr.+(4)
    
  • ++

    两个以上符号命名的方法意味着操纵的是集合元素,如:

    arr.++(5 to 8)
    
  • +=

    带有“=”号的方法意味着对自身的修改,如:

    // 改变自身的内容
    arr.+=(4)
    
  • 常用方法

    buf.trimEnd(3)				// 删除最后的三个元素
    buf.insert(0,1,2,3)			// 在0位置插入1,2,3序列
    buf.toArray()				// 转换成数组
    buf.reverse()				// 倒序
    buf.sum()					// 求和
    buf.max()					// 最大值
    buf.mkString(",")			// 对元素拼接成串
    buf.mkString("{",",","}")	// 对元素拼接成串
    

2.22 java与scala集合互操作

java集合可以和scala进行相互无缝调用,需要导入隐式转换包才可以。代码如下:

/* 自动将scala buffer转换成java list */
val list:java.util.List[String] = new java.util.ArrayList[String]()
list.add("hello")
list.add("world")
def mybuf(buf:scala.collection.mutable.Buffer[String]) = println(buf.size())
import scala.collection.JavaConversions.asScalaBuffer
mybuf(list)

/* 自动将scala buffer转换成java list */
val buf = ArrayBuffer[String]("how" , "are" , "you")
def mylist(list:java.util.List[String]) = println(list.size())
import scala.collection.JavaConversions.bufferAsJavaList
mylist(buf)

3、map操作

val t = (1 , "tomas" , 12)	// 元组
val t = (1 , "tomas")		// 对偶,对偶是特殊的元组,只有两个元素。
val t = 1 -> "tomas"		// 对偶


val map = Map(1->"tom" , 2->"tomas" , 3->"tomasLee")	// 构造map
val map = Map((1,"tom"),(2,"tomas"),(3,"tomasLee"))		// 构造map

map(1)	// 指定key,访问value
map(2)	//

// 迭代key-value
for((k,v) <- map){
	println(k + " : " + v)
}

// 迭代key
for(k <- map.keys){
    ...
}

// 迭代values
for(v <- map.values){
	...
}
原文地址:https://www.cnblogs.com/xupccc/p/9842974.html