Scala快速入门

Scala快速入门

变量定义

val hello="Hello Scala"
val hello:String="Hello Scala"
val hello:java.lang.String="Hello Scala"
lazy val hello="Hello Scala"
val hello="Hello Scala"

val x=0x29   //十六进制定义整数
val x=41      //十进制定义整数

val doubleNumber = 3.14159    //Double类型定义,直接输入浮点数,编译器会将其自动推断为Double类型
val floatNumber=3.14159F  //定义Float类型浮点数,需要在浮点数后面加F或f

val floatNumber=0.1314e1

var letter = 'A' //字符定义,用单引号(')将字符包裹

val hello = """Hello  \n \t \b \\ Scala"""
//如果需要原样输出字符串中的内容,则用三个双引号"""将字符串包裹起来

var bool = true 

*val 相当于Java中的final关键字修饰的变量,一旦赋值便不能更改 
*当未指定类型时,Scala会根据实际类型进行类型推断,上面前三种方式结果相同 
*lazy关键字修饰的变量,定义时不赋值,真正使用时才赋值 
*var关键字修饰的变量,可以被重新赋值 
*e也可以是大写E,0.1214e1 = 0.1314*10 
*e也可以是大写E,0.1214e2 = 0.1314*10*10 

函数定义

def max(x:Int, y:Int):Int={
	if(x > y)
	    x
	else
	    y
}

def sub(a:Int,b:Int)={
	a-b
}
def sub(a:Int,b:Int):Unit={
	a-b
}

*def:关键字,定义一个函数 
*max:自定义的方法名 
*(x:Int, y:Int):方法名后小扩号中为参数列表 
*Int:参数后的Int为方法返回值类型 
*{…}:大扩号中为方法体 
*Scala函数返回值可以不加return,默认函数体最后一条语句为返回值 
*函数体不指定返回值时,scala会根据实际类型进行类型推断 
*Unit关键字表示函数不存在返回值,相当于java中的void关键字 
*Scala每行语句结束后的分号可加可不加 

Scala基本类型

Value type Range
Byte 8-bit
Short 16-bit
Int 32-bit
Long 64-bit
Char 16-bit
String
Float 32-bit
Double 64-bit
Boolean true or false

算术操作+ - * / %

*在Scala中一切操作皆方法,这意味着Scala中的一切毕为对象 
*1+2整数求和时,编译器会将其转换为(1).+(2)执行,所以下面两种方式是相等的 
var sum =1+2 
var sum=(1).+(2) 

*操作符重载,编译器会将其转换为(1).+(2L)执行结果等于3 
var longsum = 1 + 2L 

Scala中可以用+ -符号来表示正负数,例如:-3+3 
var y= 1+ -3 
var y= -3+3 

关系运算符

= < ⇐ ! ==

逻辑运算符

! && ||

位运算

&(按位与) |(按位或) ^(按位异或) ~(按位取反) «(左移) »(带符号右移) »>(无符号右移)

//00000001
//00000010
//00000000
scala> 1 & 2
res0: Int = 0

//00000001
//00000010
//00000011
scala> 1 | 2
res0: Int = 3

//00000001
//1111110
scala> ~1
res1: Int = -2

//00000001
//00000010
scala> 1 << 1
res3: Int = 2

//00000001
//00000000
scala> 1 >> 1
res5: Int = 0

//00000001
//00000000
scala> 1 >>> 1
res7: Int = 0

//00000001
//00000010
//操作的结果是如果某位不同则该位为1, 否则该位为0.
scala> 1 ^ 2
res9: Int = 3

scala> 1 ^ 3
res10: Int = 2

对象比较

*Scala中的对象比较不同于Java中的对象比较 
*Scala基于内容的比较,而Java中比较的是引用地址 
*Scala eq 方法是基于引用地址的比较 

scala> 1==1
res16: Boolean = true

scala> 1==1.0
res17: Boolean = true

scala> val x="hello"
x: String = hello

scala> val y="hello"
y: String = hello

scala> x==y
res18: Boolean = true

scala> val x:String = new String("hello")
x: String = hello

scala> val y:String = new String("hello")
y: String = hello

scala> x==y
res20: Boolean = true

scala> x.eq(y)
res17: Boolean = false

运算符的优先级

扩号优先级最高 
* / % 
+ - 

= ! 
< > 

字符串的操作

var str = “hello” 
*定义的String类型变量可以使用java中String的所有方法 
*隐式转换:Scala把String类型转换成StringOps,其中包括了所有的immutable sequence的方法。碰到reverse,map,drop和slice方法时编译器会自动插入这个转换。 
*Scala方法的调用可以不加点“.”,直接用空格调用,并且可以省略扩号 

str.indexOf(“o”)
str indexOf 'o'
str.toUpperCase
str.toLowerCase
str.reverse
str.map(_.toUpper)
str.drop(2)
str drop 2
str drop(2)
str slice(1,4)
str.slice(1,4)
….

if的使用

scala> var x = if("hello"=="hello")1 else 2 
x: Int = 1
scala> var x = if("hello"=="hello")"1" else "2"
x: String = 1

*Scala会自动进行类型推断

while的使用

  def main(args: Array[String]): Unit = {
    HelloScala loop 4
    HelloScala loop(4)
    HelloScala.loop(4)
    var line=""
    while((line=readLine())!="")   //readLine() 读取控制台的输入
      println("read:"+line)
  }

  def loop(x:Int)={
    var a=x
    while(a!=0){
      a=a-1
      println(a)
    }
  }

do while的使用

  def main(args: Array[String]): Unit = {
    HelloScala loop(4,2)
    HelloScala.loop(4,2)

    var line=""
    do{
      line=readLine()
      println("read:"+line)
    }
    while(line!="")
 }
 def loop(x:Int,y:Int)={
    var a=x
    do{
      a=a-y
      println(a)
    }
    while(a!=0)
 }

*Scala具有函数式编程语方的特点,在函数式编程语方当中,一般不推荐使用var变量 
*利用if替代while控制结构,可以减少var变量的使用,程序结构也更简单,表达能力更强 

  def loop(x:Int):Unit={
    if(x!=0){
      println(x)
      loop(x-1)
    }
  }

for循环的使用

1.打印当前目录所有文件名 
*← 生成器(generator),在执行过程中,集合files中的Array[File]的元素将依次赋值给file,file类型为File,输出时调用其toStirng方法将文件名打印出来 

val files = (new java.io.File(".")).listFiles
for(file <- files )println(file)
val files = (new java.io.File(".")).listFiles
for(i <- 0 to files.length -1)println(files(i))
var a = 1 to 2
for(i <- a)println("item:"+i)

2.for循环中加入if过滤操作

val files = (new java.io.File(".")).listFiles
for(file <- files if file.getName.endsWith("iml"))println(file)

3.加入多个过滤条件

for(file <- files if file.isFile; if file.getName.endsWith("iml")) println(file)

4.多重循环的实现

def main(args: Array[String]): Unit = {
    grep("JAVA")
 }

 def fileLines(file: File) = scala.io.Source.fromFile(file).getLines.toList

 def grep(pattern:String) =
    for (
      file <- (new File(".")).listFiles if file.getName.endsWith("iml");
      line <- fileLines(file) if line.trim.contains(pattern)
 ) println(file + ":" + line.trim)

yield 关键字在循环中生成返回结果

每次循环会把值保留,执行完后会把所有值转换为数组Array[File]类型并返回

  def main(args: Array[String]): Unit = {
    println(getFile(0))
  }

  def getFile =
    for{
      file <- (new File(".")).listFiles if file.getName.endsWith("iml")
    }yield file
  def main(args: Array[String]): Unit = {
    for(i <- grep("orderEntry"))println(i)
  }

  def fileLines(file: File) =
    scala.io.Source.fromFile(file).getLines.toList

  def grep(pattern:String) =
    for (
      file <- (new File(".")).listFiles if file.getName.endsWith("iml");
      line <- fileLines(file) if line.trim.contains(pattern)
    ) yield line.trim
//返回Array[String]

Array数组操作

定长数组Array

Scala中的Array是以Java中的Array方式实现的 

var arr = 0 until 5 
scala.collection.immutable.Range = Range 0 until 5 

val arr1 = new Array[Int](10) 
复杂对象类型的数组初使化值为null,数值型被初使化为0 

var arr2 = Array(“aaa”,“bbb”) 
定义一个数组同时赋值,这种调用方式是调用其apply方法进行数组创建操作的 

arr2(1)=“test” 
数组元素赋值,不同于Java,这里index的指定是用小扩号。 

intArr.update(2,“test2”) 
更新值 

变长数组ArrayBuffer

scala.collection.mutable.ArrayBuffer 

var arr=ArrayBuffer[String]() 
arr+=“Hello” 
arr+=(“Hello”,“Scala”) 
+= 在尾部添加元素 

arr.insert(1,“test1”,“test2”,“test3”) 
arr.insertAll(3,arr) 
arr.insertAll(3,arr2) 
在指定位置插入数据 

arr.remove(0,2) 
从索引0开始,删除2个元素 

arr++=Array(“hello”,“test”) 
arr++=List(“value1”,“value2”) 
++=用于向数组中追加内容,++=右侧可以是任何集合 

arr.trimStart(2) 
删除前面2个元素 

arr.trimEnd(2) 
删除未尾2个元素 

arr.toArray 
转换ArrayBuffer to Array 

arr.toBuffer 
转换Array to ArrayBuffer 

遍历数组 
to 方式 
for(i ← 0 to arr.length-1)println(arr(i)) 

until方式 
for(i ← 0 until arr.length)println(arr(i)) 

foreach方式 
for(i ← arr)print(“\t”+i) 

指定步长 
for(i← 0 until (arr.length,2)) print(“\t”+arr(i)) 
for(i← (0 to (arr.length-1,2))) print(“\t”+arr(i)) 

倒序输出 
for(i ← (0 until arr.length).reverse) print(“\t”+arr(i)) 
for(i ← (0 to arr.length -1).reverse) print(“\t”+arr(i)) 
for(i ← arr.reverse) print(“\t”+i) 

yield返回新的数组 
var arr2 = for(i ← arr) yield i+“test” 
*原数组不变 
*BufferArray转换后产生的仍然是BufferArray 
*Array转换后产生的仍然是Array 

数组求和,最大值,最小值,格式化输出,过滤掉小于3数据 
val intArr = Array(1,2,3,4,5) 
println(intArr.sum) 
println(intArr.max) 
println(intArr.min) 
println(intArr.mkString) 
println(intArr mkString “,”) 
println(intArr.mkString(“(”,“,”,“)”)) 
println(intArr.dropWhile(_<3) mkString “,”) 

多维数组 
var multiArr = Array(Array(1,2,3),Array(4,5,6)) 
println(multiArr(1)(2)) 
for (elem ← multiArr) {println(elem mkString(“,”))} 

List

List的定义

val cars = List(“bmw”,“volvo”) 
val cars = List.apply(“bmw”,“volvo”) 
val nums = List(1,2,3,4,5,6,7,7,8) 
var cars:List[Object]=List(“BMW”,“Volvo”) 
var list= List() 
var cars:List[String]=List() 

采用 :: 及Nil进行列表构建 
val nums = 1 :: (2 :: (3:: (4::Nil))) 
相等于 
val nums = List(1, 2, 3, 4) 
相等于 
val nums = 1::2::3::4::Nil 

多重List 
val cars=List(List(“BMW”,“200万”,“red”),List(“BYD”,“20万”,“white”)) 

*list一旦被创建,其值不能被改变 
*list具有递归结构(Recursive Structure),例如链表结构 
*List类型和其它集合类型一样,它具有协变性(Covariant),即对于类型S和T,如果S是T的子类型,则List[S]也是List[T]的子类型 
*空的List,其类型为Nothing,Nothing在Scala的继承层次中的最低层,即Nothing是任何Scala其它类型如String,Object等的子类 
* :: 操作符的优先级是从右往左的 

list常用操作

判断是否为空 
cars.isEmpty 

取第一个元素 
cars.head 

取第一个元素外的元素列表 
cars.tail 
cars.reverse.init 

init取最后一个元素外的元素列表 
cars.init 
cars.reverse.tail 

取最后一个 
cars:last 

取第二个元素 
cars.tail.head 

取倒数第二个元素 
cars.init.last 

元素倒置 
cars.reverse 

丢弃前N个元素,返回元素列表 
cars drop 1 

获取前几个元素列表 
cars take 2 
cars.take(2) 

将列表进行分割,从Index N的位置进行分割,返回前后两个元素列表,位置N算后面的元素列表 
cars.splitAt(1) 
(cars.take(1),cars.drop1) 

zip 返回的是List类型的元组(Tuple) 

scala> val arr = List("1","6","3","5","9") 
arr: List[String] = List(1, 6, 3, 5, 9) 

scala> val num = List(1,6,3,5,9) 
num: List[Int] = List(1, 6, 3, 5, 9) 

scala> arr zip num 
res99: List[(String, Int)] = List((1,1), (6,6), (3,3), (5,5), (9,9)) 

插入排序算法

def sort(xs:List[Int]) :List[Int] ={
	if(xs.isEmpty) Nil
	else insert(xs.head, sort(xs.tail))
}

def insert(x:Int, xs:List[Int]) :List[Int] ={
	if(xs.isEmpty || x<= xs.head) x:: xs
	else xs.head :: insert(x,xs.tail)	
}

List连接操作 :::

scala> List(1,2):::List(3,4)
res35: List[Int] = List(1, 2, 3, 4)

list相等判断

val arr = List(1,6,3,5,9) 
val arr1 = List("1","6","3","5","9") 
aaa == arr1  //false 
val arr = List("1","6","3","5","9")
val arr1 = List("1","6","3","5","9")
arr == arr1  //true

range方法,构建某一值范围内的List 
val nums = List.range(2,9) 
range主法,指定步长N,范围不存在的返回空List 
val nums = List.range(2,100, 5) 
val nums = List.range(100,20, -5) 

flatten,将列表平滑成第一个元素

scala> List(List("aaa","bbb"),List("111","222")).flatten 
res34: List[String] = List(aaa, bbb, 111, 222) 

concat列表链接 

scala> List.concat(List("aaa","bbb"),List("111","222")) res32: List[String] = List(aaa, bbb, 111, 222) \\

Set

Set 不可重复,无序的集合 
如果需要按添加顺序排序,可以使用LinkedHashSet实现 

val set = Set(1,2,3) 
val mutableSet = mutable.Set(1,2,3) 

添加元i 
set+5 

遍历Set 
for(i ← set+7)print(i) 

Map

val map = Map(1 → “one”,“two” → 2,2.3 → “three”) 
val mutableMap = mutable.Map(1 → “one”,“two” → 2,2.3 → “three”) 
println(map) 

添加元素 
println(map.+(4 → “four”)) 

删除元素 
println(map.-(“tow”)) 

遍历map 

for(i<-map)println(i+"\t"+i._1+"\t"+i._2)  
map.foreach(e=>{
      val (k,v)=e
      println(k,v) //通过模式匹配获取元组内容
      println(e._1,e._2) //直接访问元组内容

})

mutable map可以使用put添加元素 
val mutableMap = mutable.Map(1 → “one”,“two” → 2,2.3 → “three”) 
mutableMap.put(“four”,4)

判断key是不存在 map.contains(1) map.get(“key”)

Queue队列

immutable queue 
scala> var queue=scala.collection.immutable.Queue(1,2,3) 
queue: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3) 

出队 
scala> queue.dequeue 
res38: (Int, scala.collection.immutable.Queue[Int]) = (1,Queue(2, 3)) 

入队 
scala> queue.enqueue(4) 
res40: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3, 4) 

mutable queue 
scala> var queue=scala.collection.mutable.Queue(1,2,3,4,5) 
queue: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5) 

入队操作 
scala> queue += 5 
res43: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5, 5) 

集合方式 
scala> queue ++= List(6,7,8) 
res45: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5, 5, 6, 7, 8) 

Scala.collection

scala会默认导入以几个包: 
import java.lang_ 
import scala._ 
import Predef._ 

*Predef对象中包含了Set、Map等的定义 
*在Scala中,默认使用的immutable集合,如果需要使用mutable集合,需要在在程序中import 
*immutable 不可变的集合,一量被创建,便不能被改变,添加、删除、更新操作返回的是新的集合,原集合保持不变 
*mutable 可变的集合,可以更新或修改,添加、删除、修改元素将作用于原集合 

scala.collection包中的集合类层次结构如下图: 

Scala快速入门_第1张图片


scala.collection.immutable包中的类层次结构: 

Scala快速入门_第2张图片


scala.collection.mutable包中的类层次结构: 
Scala快速入门_第3张图片


可变集合与不可变集合对应关系: 

Scala快速入门_第4张图片

函数字面量(值函数)

函数字面量(function literal),也称值函数(function values),指的是函数可以赋值给变量。

val increase=(x:Int)=>x+1
//=>左侧的表示输入参数,右侧的表示方法体
//等同于
def increase(x:Int)=x+1

    //方法体中多个语句则使用{}
val increase=(x:Int)=>{
      println("begin")
      println("end")
      x+1
}
//数组的map方法中调用(写法1)
//写法1
println(Array(1,2,3).map(increase).mkString(“,”))
//写法2 匿名函数写法
println(Array(1,2,3).map((x:Int)=>x+1) mkString “,”)

函数简化

*大扩号中只有一行操作时,大扩号可以省掉, 
*方法的调用可以省略“.”,用空格代替 
*参数类型推断写法 

println(Array(1,2,3) map((x)=>x+1) mkString ",")
println(Array(1,2,3) map((x)=>x+1) mkString(","))

*函数只有一个参数的话,可以省略()

scala> Array(1,2,3,4) map{x=>x+1} mkString(",")
res28: String = 2,3,4,5

*如果参数右边只出现一次,则可以进一步简化

scala> Array(1,2,3,4) map{_+1} mkString(",")
res29: String = 2,3,4,5

*值函数简化

val fun1=1+(_:Int)
val fun2:(Double)=>Double=1+_

*函数参数,即将一个函数做为参数传入

def convertIntToString(f:(Int)=>String)=f(4)

def multiply(factor:Double)=(x:Double)=>factor*x
    var b = multiply(4)
    println(b(1))

函数闭包(Closure)

(x:Int)⇒x+more,这里的more是一个自由变量(Free Variable),more是一个没有指定含义的不定变量 
而x的类型确定,值在函数调用的时候被赋值,称这种变量为绑定变量(Bound Variable) 

(x:Int)=>x+more 

 var more=3 
 var fun = (x:Int)=>x+more

 more =10
 println(fun(1))
 println(fun(13))

 more =10.87
 println(fun(1))
 println(fun(13))
var sum=0
val list = List(1,2,3,4,5,6,7,88,9)
list.foreach(sum+=_) 

*像这种运行时确定more类型及值的函数称为闭包,more是个自由变量,在运行时值和类型得以确定,这是一个由开放(free)到封闭的过程。


你可能感兴趣的:(Scala)