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每行语句结束后的分号可加可不加
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) ….
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会自动进行类型推断
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) } }
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) } }
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)
每次循环会把值保留,执行完后会把所有值转换为数组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]
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”)
更新值
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(“,”))}
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等的子类
* :: 操作符的优先级是从右往左的
判断是否为空
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 不可重复,无序的集合
如果需要按添加顺序排序,可以使用LinkedHashSet实现
val set = Set(1,2,3)
val mutableSet = mutable.Set(1,2,3)
添加元i
set+5
遍历Set
for(i ← set+7)print(i)
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”)
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会默认导入以几个包:
import java.lang_
import scala._
import Predef._
*Predef对象中包含了Set、Map等的定义
*在Scala中,默认使用的immutable集合,如果需要使用mutable集合,需要在在程序中import
*immutable 不可变的集合,一量被创建,便不能被改变,添加、删除、更新操作返回的是新的集合,原集合保持不变
*mutable 可变的集合,可以更新或修改,添加、删除、修改元素将作用于原集合
scala.collection包中的集合类层次结构如下图:
scala.collection.immutable包中的类层次结构:
scala.collection.mutable包中的类层次结构:
可变集合与不可变集合对应关系:
函数字面量(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))
(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)到封闭的过程。