scala基础

基本框架

class Teat1{
    def hello(){ ... }  
}
object Test{//名字相同的话会变成伴生对象,后面会介绍
    
    //Scala没有static修饰词,而object单例类(相当于静态类)能代为实现static功能,所以main方法出现在object类中。
    def main(args: Array[String]): Unit = {
        val str = "aaa"
        printin(str)
        Teat1.hello() //不需实例化,直接用
    }
}

由于相当于静态类,object中定义的方法在使用时就是“类名.方法名”

val a = 123 //“引用”不可变,如果是array,里面的元素可变(引入包的情况下), var可变
val a: Int = 123//也可

数据类型(无引用类型)

Byte, Char, Short, Int, Long, Float, Double, Boolean等
其他Unit, Null, Nothing, Any, AnyRef
AnyVal相当于java的object
Unit相当于void

判断,循环,方法和函数

//判断
val y = if(x>1) 1 else -1
val z = if(x>1) 1 else "error"

//循环
1 to 10 //1.to(10)
1 until 10 //1到9
for(i<-1 to 10){...}
for(i<-arr) println(i)
for(i<-arr.reverse) println(i)
for(i<-1 to 3; j <- 1 to 3 if (i !=j)) println(i*10+j)
val res = for(i <- 1 until 10) yield i //yield生成vector(....)
//跳出循环的三种方式,boolean, 函数中的return, break
while (flag){
    ....
    if (condition) flag = false
}

def test() : Int = {    
    var i = 0
    while (true) {
        i += 1
        if (i == 5) {return i}
    }
}

import scala.util.control.Breaks._
var i = 0
breakable{
    while (true) {
        i += 1
        if (i == 5) break
    }
}

//方法
def m1(x: Int, y:Int): Int = x + y
m1(3,4)
def m1(x:Int) = x*x //也可以
//函数
val f1 =(x: Int, y:Int) => x+y
f1(2,3)
val f1:

//方法用函数作参数
def m2(f:(Int, Int)=> Int) =f(2,4)
val f1 =(x:Int,y:Int) => x+y
m2(f1)//结果为7

//方法转换为函数
val f1 = m1 _

数组

定长
val arr1 = new Array[Int](8) //调用静态类
println(arr1.toBurrer)
val arr2 = Array("java","scala","c#")
println(arr2(0))
Array.fill(4)(0)
Array.ofDim[Int](3,4)//二维空数组,(1)(1)取值
val multiDimArr = new Array[Array[Int]](3)//同上n维数组,但可自定义里面一层每个数组的长度

变长
import scala.collection.mutable.ArrayBuffer
val arr3 = ArrayBuffer[Int]()
arr3 +=(2,3,4)//得(2,3,4)
arr3.insert(0,-1,0)//结果为(-1,0,2,3,4)
arr3.remove(2,2)//在index=2删两个

方法
sorted, reserve, min, max, sum, head, last, tail, count(p: (T) ⇒ Boolean): Int, exists, filter, filterNot, take, drop, takeWhile(p: (T) ⇒ Boolean): ArrayBuffer取subArray,直到不符合,后面符合的不管, dropWhile, contains, startWith(that: GenSeq[B], offset: Int): Boolean, indexOf
例子:
count(_ % 2 == 0)//返回符合条件的元素数量
java.util.Arrays.equals(a, b)//比较两个array
a.sameElements(b)//Array[String]用这个

zip
arr1.zip(arr2).toMap//新arr,每个pair为Tuple2,可转为Map

集合

序列list

//不可变
val list1 = List(1,2,3)
val list2 = 0 +: list1//结果在list1前面加个0,也可::
val list3 = list1.::(0)//结果和上面一样 
val list4 = list :+ 4//在后面加4
val list5 = list1 ++ list2//合并两个,也可++: or :::
//可变
import
val list1 =ListBuffer(6,7,8)
list1 ++= list2//可变后,list1重新引用++生成的新值
list5.append(5)
  • :: 头部追加数据 x::listx为加入到头部的元素,无论x是列表与否,它都只将成为新生成列表的第一个元素)等价于list.::(x)`。该符号还可用于配型匹配
  • :++: 追加,冒号靠近集合类型
  • ::: 两个List类型
  • ++ 两个集合list1++list2

映射map

map("scala"->1)
map((scala, 1))
#要引入包后重新创建才能改里面的值
map.getOrRlse("c#",-1)//最好用这种方式取值,直接用map("c#")会出一大串错误

//数组转换为map
arr.toMap

val map1 = new HashMap[String, Int]()
map1("scala")=1
map1 +=(("java",2))
map1.put ("c++",5)

元组

//不可变
val t = ("scala", 3,14, ("spark",1))//index从1开始
t._1
t._4._1
val t,(a,b,c) = ("scala", 3,14, ("spark",1))

//HashSet要import
import
val set1 = new HashSet[Int]()
val set3 = set2 ++ Set(2,3,4)
//可变
import
set += 1

方法
set.remove()或-=

练习

1.基础

//创建list
val list0 = List (1,2,3,4,5)
//将list0中每个元素乘以2,并创建新list
val list1 = list0.map(_ *2)//下划线df示逐个地取出list0里所有元素
//将list0中的偶数取出来生成新集合
val list2 = list0.filter(_ % 2 ==0)
//将list0排序后反转生成新集合
val list3 = list0.sorted.reverse//没有参数不需加()
//将list0中元素4个一组,生成迭代
val it = list0.grouped(4)// println(it.toBuffer)查看
//迭代器转为list
val list4 = it.toList//得到List(List(),List()..)
//压扁
val list5 = list4.flatten
//先按空格切分再压扁
val lines = ("hello world","..","..")
val worlds = lines.map(_.split(" "))//得出三个不知道是什么的object
val flatWords = words.flatten
//或
val flatWords2 = lines.flatMap(_.split(" "))
//并行计算求和
val arr=Array(1,2,3,4)
val res = arr.par.sum//进程分配随机
//特定顺序进行聚合
val res = arr.reduce(_+_)//相当于reduceLeft
val res = arr.par.reduce(_+_)//注意这种情况不能用减法
//折叠
val res = arr.fold(0)(_+_)//在fold这个初始值上聚合;实现了柯里化
val res = arr.foldLeft(10)(_+_)
val res = List(1,2,3,4).foldRight(10)(_-_) //结果是8,1-(2-(3-(4-10))),相当于右边的_作为累加器
//聚合
val list6 = List(List(),List()..)
val res = list6.flatten.reduce(_+_)
val res = list6.aggregate(0)(_+_.sum, _+_)//0代表每个循环的初始值,第一个_为初始值,第二个为第一个内部List,第二个_+_为不同内部List的求和
//集
val l1=List(1,2,3)
val l2=List(1,2,3)
val res =l1 union l2 //还有diff, intersect,结果为List

2.wordcount

object WordCount{
    def main(args: Array[String]): Unit = {
        val lines = List("hello world","hello scala","")
        //压平
        val words = lines.flatMap(_.split(" "))
        //生成键对
        val pair = words.map((_,1))//每个string变为对,仍未List
        //分组
        val grouped = pair.groupBy(_._1)//注意这里_1取得1(元组从1开始),然后变为Map,如scala映射List((scala,1),(scala,1),(scala,1))。另外,groupByKey后是key和value分开的,即(key,(1,1,1,1))。groupBy缺是保留的
        //统计
        val total = grouped.mapValues(_.size)//对value进行操作,_为List((scala,1),(scala,1),(scala,1)),求其size。最终结果还是Map
        //排序
        val sorted = total.toList.sortBy(_._2)
    }
}

class

//伴生对象用object修饰,且名字要跟class名字一样
//一般object修饰为静态类
class Person {
    val id: String = "100" //只有get方法
    var name: String = _ //有get有set,会获取null
    private var age: Int = _ //伴生对象也访问,会获取0
    private[this] val gender = "男" //伴生也不能访问
}

object Person{
    def main(args: Array[String]): Unit = {
        val p = new Person
        
}

object Test{
}

说明:

1.Scala把类中的static集中放到伴生object对象中,伴生对象和类文件必须是同一个源文件,可以用伴生对象做一些初始化操作.

2.object不能提供构造器参数,也就是说object必须是无参的

//括号内为构造器,默认为val。faceValue的值伴生对象也不能访问
class StructDemo(val name: String, var age: Int, faceValue: Int = 90){
    
    val gender: String = _
    def getFaceValue(): Int = {
        FaceValue//最后一句代码的值作为返回
    }
    //辅助构造器
    def this(name: String, age: Int, faceValue: Int, gender: String){
    this(name, age, faceValue)
    this.gender = gender
}


object StructDemo{
    def main(args: Array[String]): Unit = {
        val s = new StrucDemo("abc", 26, 98)
    println(s.getFaceValue)//这样才能访问FaceValue
    }
}
//object修饰的类实现单例模式,用作工具类,存放常量,工具方法
//单例模式,就是该类最多只存在一个实例。在多线程下,有三种策略(加锁,预先创建和双重加锁)
object StructDemo{
    def main(args: Array[String]): Unit = {
    
    val factory = SessionFactory
    println(factory.getSessions)
    println(factory.getSessions.size)
    println(factory.getSessions(0))
    println(factory.removeSession)
    //结果为:
    //SessionFactory被执行
    //一个ArrayBuffer, 里面有五个Session类
    //5
    //第一个Session
    //...
    //()来源于Unit
    }
}
object SessionFactory{
    println("SessionFactory被执行")
    var i = 5
    private val session = new ArrayBuffer[Session]()
    while(i>0){
        session += new Session
        i -= 1
    }
    
    def getSessions = session
    def removeSession: Unit = {
        val s = session(0)
        session.remove(0)
        println("...")
        
}
class Session{}
//类和其半生对象可以互相访问私有变量。list =List(1,2,3,4])就调用了半生对象,都没有用new
class Dog{
    private var name = "..."
    def printName():Unit ={
        println(Dog.CONSTANT + name)
    }
}

object Dog{
    private val CONSTANT = "..."
    def main(args: Array[String]): Unit = {
    val p = naw Dog
    println(p.name)
}
class ApplyDemo(val name: String, var age: Int, var faceValue: Int){

}
object ApplyDemo{
    def apply(name: String, age: Int, faceValue: Int): ApplyDemo = new ApplyDemo(name, age, faceValue)//注入方法,在半生对象里用于初始化;其参数不需要和构造器的统一
    def unaply(applyDemo: ApplyDemo):Option[(String, Int, Int)] = {
        if (applyDemo == null){
            None
        }else{
            Some(applyDemo.name, applyDemo.age, applyDemo.faceValue)//对应上面的option
        }
    }//提取方法,用于提取固定数量的对象,返回一个序列(Option),内部用Some来存放
}
object Test{
    def main(args: Array[String]): Unit = {
    val applyDemo = ApplyDemo("...", 24, 90) //不需要用new,直接用类名就会引用半生对象,加参数就引用apply方法
    applyDemo match {
        case ApplyDemo("...", age, faceValue) => println(s"age: $age")//非赋值的情况下,就会用unapply
        case _ => println("no match")
    }
}
//表明哪个包有访问权限
//第二个private表明只有伴生可访问,在其他类使用s.faceValue可以通过IDE的检查,但是执行时并不能执行
private [package_name]class private PrivateDemo(val gender: Int, var faceValue: Int){
    private val name = "..."//私有字段
    private[this] var age = 23//对象私有字段
    private def sayHello(): Unit = {
        println(s".. $age")
    }
}
object ClassDemo{
    def main(args: Array[String]): Unit = {
    }
}
//特质
trait Flyale{
    //声明一个没有值的字段
    val distance: Int
    //没有实现的方法
    def fight: String
    //实现了的方法
    def fly: Unit = {
        println()
    }
}
//抽象类
abstract class Animal{
    //声明没有赋值的字段
    val name:String
    //没有实现的方法
    def run(): String
    //有实现的
    def climb: String ={
        "..."
    }
}
//如果只实现特质,直接用extends
class Human extends Animal with Flyable{
    //补充没有赋值的变量
    //补充抽象类没有实现的方法,当然已经实现了的也可以
    //实现上面特质没有实现的方法
}

内部类:下面每个Class的实例都有一个对应的Student类。如果c1和c2都是Class的实例,leo是c2通过register创建的Student,则c1.studentList += leo会出错。如果把内部类放到伴生对象中,或者运用类型投影,则上述行为可以实现。

class Class{ out => //加上这个,Student就可以调用其自身定义的方法
    class Student(name : String){}
    val studentList = new ArrayBuffer[Student]//当class Student被放到伴生对象中时,这里Student要改为Class.Student;类型投影改为Class#Student
    def register(name : String) : Student = {new Student(name)}
}

匹配

object MatchStr{
    def main(args: Array[String]): Unit = {
        val arr = Array("..", "jfkdjfk", "dfjdk")
        val name = arr(Random.nextInt(arr.length))
        println(name)
        name match{
            case ".." => println("点点")
            case "jfkdjfk" => println("乱语")
             case _ => println("Nothing")
            
        }
    } 
object MatchType{
    def main(args: Array[String]): Unit = {
        val arr = Array("..", 100, True, MatchType)
        val element = arr(Random.nextInt(arr.length))
        println(element)
        element match{
            case str:String => println("点点")
            case int:Int => println("乱语")
            case _: Any => println("Nothing")
            
        }
    } 
class MatchTest{
}
object MatchArr_Set_List{
    def main(args: Array[String]): Unit = {
        //数组
        val arr = Array(1,2,3,4)
        arr match{
            case Array(1,a,b,c) => println("点点")
            case Array(_,x,y) => println("乱语")
            case _ => println("Nothing")
            
        }//a,b,c和_一样?
        //元组
        val tup = (1,2,3,4)
        tup match{
            case (1,a,b,c) => println("点点")
            case (_,x,y) => println("乱语")
            case _: Any => println("Nothing")
        }
        //序列
        val list1 = List(1,2,3,4)
        tup match{
            case List(1,2,3,a) => println("case1") 
            case 0::Nil => println("点点") //Nil为空List
            case a::b::c::d::Nil => println("乱语")//::表示从右向左合并集合,第一个默认为List
            case _: Any => println("Nothing")
class MatchTest{
}
object MatchClass{
    def main(args: Array[String]): Unit = {
        val arr = Array(CheckTimeOoutTask, SubmiTask("sdwg", "dfeg"), HearBeat(10), MatchType)
        val arr(Random.nextInt(arr.length)) match{
            case HearBeat(time) => println("点点")
            case SubmiTask(sbg, task) => println("乱语")
            case CheckTimeOoutTask => println("Nothing")            
        }
    } 
case class HearBeat(time:Long)//样例类,默认有getter, setter, apply 和 unapply
case class SubmiTask(id:String, taskName:string)
case objec CheckTimeOoutTask //单例类

添加case能够给class或object带来下面变化

  1. pattern matching support
  2. default implementations of equals and hashCode
  3. default implementations of serialization
  4. a prettier default implementation of toString, and
  5. the small amount of functionality that they get from automatically inheriting from scala.Product.

另外,对于case class,实例化不用new。但对于case objec,我们一般只用到它的serialization和toString特征。

偏函数

//m1等价于m2
//String为参数类型,Int为输出类型
//常用做输入模式匹配
//def可以改为val
def m1: PartialFunction[String, Int] = {
    case "one" => 1
    case "two" => 2
    case _ => 0
}

def m2 (num:String): Int = num match {
    case "one" => 1
    case "two" => 2
    case _ => 0
}

m1.isDefinedAt("string")//判断string是否符合其中一个case
m1("one")//返回1。实际上是调用了apply方法,该方法的调用就是直接名称加参数name(arg)。这也是为什么Scala创建对象不需要new的原因

高阶函数

arr.map(func) //相当于python的lambda函数

柯里化

def currying(x:Int)(y:Int)=x*y//也可以def curry(x: Int) = (y:Int) => x*y
currying(3)(4) //12
val curry = currying(3) //先给一个值
curry(4) //12
def m2(x:Int)(implicit y:Int=5)=x*y
m2(4) //20
m2(4)(3) //12
implicit val x = 100
m2(5) //500
implicit val y = 100
m2(5) //出错,因有多个implicit
val arr = Array(("scala", 1),("scala",2))
arr.foldLeft(0)(_+_._2) //6

//练习
object Context{ //这个放在CurryingDemo下面会出错。不过这段一般放到其他页面里
    implicit val a = "java"
    implicit val b = "python"
}

object CurryingDemo{
    def m1(str:String)(implicit name:String = "scala")={
        println(str + name)
    }
    
    def main(args: Array[String]): Unit = {
        //val func = m1("Hi") 这里会出错,m1没有返回值,但这里却用了=,除非上面去掉println
        import Context.a //这样implicit才不会混淆
        m1("Hi")
    }
}

隐式

什么情况出现隐式:方法中传入的参数类型不匹配;对象引用的方法在其本身的类中不存在;类调用其自身方法,但导入的类型不匹配 。这些情况下,程序就会去搜索implicit的函数,看有没有把不匹配的类型转化成匹配类型。
Scala默认搜索1.源类型及其伴生对象内2.当前程序作用域找隐式函数。否则要用import,建议在需要用的时候才import,比如在某个函数或方法内,减少转化对其他代码的影响

//隐式转换
implicit def dog2person(obj:Object): Person = if (obj.isInstanceOf[Dog]){
    val dog = obj.asInstanceOf[Dog]; new Person(dog.name)) else Nil
//加强现有类型,下面规定只转换Man。这样,即便Man没有Supermen的方法,man对象依然能用Supermen的方法
implicit def man2superman(man:Man): Supermen = new Superman(man.name)
//导入import隐式转换

//隐式参数
class SignPen{ 
    def write(content:String) = println(content)
}
implicit val = signPen = new SignPen
def signForExam(name:String)(implicit signPen:SignPen){
    signPen.write(name+"...")
}
signForExam("leo") //这样就已经可以执行SignPen的write了
    

object MyPredef{ //day1package里另一个class MyPredef
    implicit def fileToRichFile(file:String) = new RichFile(file)
}

class RichFile(val file: String){
    def read():String = {
        Source.fromFile(file).mkString("")
    }
}
object RichFile{
    def main(args: Array[String]): Unit = {
        //显式
        val file = "path"
        val content: String = new RichFile(file).read()
        println(content)
        //隐式
        import day1.MyPredef.fileToRichFile
        val file = "path"
        val content = file.read()
        println(content)
    }
}
    
//导入Java和Scala的隐式转换
import scala.collection.JavaConversions.asScalaBuffer//可将Java类方法生成的List变为Buffer
import scala.collection.JavaConversions.bufferAsJavaList//可以将ArrayBuffer传入Java类的方法中(变为List)进行使用

练习

object ImplicitContext{
    implicit object OderingGirl extends Ordering[Girl]{
        override def compare(x:Girl,y:Girl): Int = if (x.faceValue > y.faceValue) 1 else -1
    }
}

class Girl(val name: String, var faceValue: Int){
    override def toString: String = s"$name, $faceValue"
}
class Goddess[T:Odering](val v1: T, val v2:T){
    def choose()(implicit ord: Ordering[T]) = if (ord.gt(v1,v2)) v1 else v2
}

object Goddess{
    def main(args: Array[String]): Unit = {
    import ImplicitContext.OderingGirl
    val g1 = new Girl("",90)
    val g2 = new Girl("",80)
    val goddess = new Goddess(g1,g2)
    val res = goddess.choose()
    println(res)

泛型

基础

//泛型类
class Student[T](val localId:T){
    def getSchoolId(hukouId:T) = "S-" + hukouId + "-" + localId
}
val marry = new Student[Int](1) //scala会根据传入参数自动判断类型,此处不加[Int]也行
//泛型函数
def getCard[T](content:T) ={
    if(conent.isInstanceOf[Int]) ""
    else if(conent.isInstanceOf[Int]) ""
    else ""
}

[B <: A]上界,A为父类
[B <% A]B类型要转换成A类,B可以是A类、其子类或者通过隐式类型转换的类型

class Person(val name:String){
    def makeFriends(p:Person){}
}

class Student(name:String) extends Person(name) //有了这个Student才能进入Party(进入的必须为Person的子类)
class Party[T <: Person](p1: T, p2: T){
    def play = p1.makeFriends(p2) //有了上界是这里makeFriends成为可能
}

class Dog(val name: String){}

//隐式类型转换
implicit def dog2person(obj:Object): Person = if (obj.isInstanceOf[Dog]){
    val dog = obj.asInstanceOf[Dog]; new Person(dog.name)) else Nil

[B : A] context bound需要一个隐式转换的值?

class Calculator[T:Ordering](val number1: T, val number2: T){
    def max(implicit order: Ordering[T]) = if (order.compare(number1,number2)>0) number1 else number2
}
val cal = new Calculator(1,2)
cal.max

//Manifest ContextBounds
//如果生成两个类,meat和vegetable,他们都能放到下面的方法里面
def packageFood[T:Manifest](foods:T*) = { //可以放多个参数
    val foodPackage = new Array[T](foods.length)
        for (i <- 0 until foods.length) foodPackage(i) = food(i)
        foodPackage
}

[-A]逆变,作为参数类型,如果A是T的子类,那么C[T]C[A]的子类
[+B]协变,作为返回类型,如果B是T的子类,那么C[B]C[T]的子类

class Master
class Professional extends Master
class Card[+T](val name:String)//这样下面的a和b都可以用enterMeet,因为Professional父类为Master,Card[+T]使得传入的子类协变为父类,所以Card[父类]才能用的方法,Card[子类]也能用
def enterMeet(card: Card[Master]){}
val a = new Card[Master]("a")
val b = new Card[Professional]("b")
class UpperBoundDemo[T <: Comparable[T]{
    def select(first: T, second: T): T= {
        if (first.compareTo(second) > 0) first else second
    }
}

object UpperBounDemo{
    def main(args: Array[String]): Unit = {
        val u = new UpperBoundDemo[MissRight]
        
        val m1 = new MissRight("",123)
        val m2 = new MissRight("",125)
        
        val res = u.select(m1,m2)
        println(res.name)
    }
}

class MissRight(val name: String, val faceValue: Int) extends Comparable[MissRight]{
    override def compareTo(o:MissRight):Int = {
        this.faceValue - o.faceValue
    }
}

重写field

//下面代码中,创建的PEStudent的classScores会是Array[Int]()。原因是自类的默认构造函数会先调用夫类的默认构造函数,但由于classNumber将要被重写,这可能使得getter方法取出了null值,这时classScores的创建结果就是Array[Int]()
class Student {
    val classNumber: Int = 10
    val classScores: Array[Int] new Array[Int](classNumber)
}

class PEStudent extends Student {
    override val classNumber: Int = 3
}
//下面这种方式是在调用夫类构造函数之前就已经重写好classNumber,所以结果会是Array[Int](3)
class PEStudent {
    override val classNumber: Int = 3
} extends Student

Scala继承层级

顶端是两个trait,Nothing(Any类继承)和Null(null对象)

Any增加了isInstanceOf, equals, hashCode等方法

Anyval和AnyRef都继承了Any,前者是所有值类的基类,后者是所有引用类的基类增加了wait, notify, synchronized等方法。

对象相等行:重写equals方法,一般先asInstanceOf[class],判断是否为null,然后比较该对象的成员变量是否相等。最后要重写hashCode方法,一般是各变量的.hashCode相加。

I/O

//读
import scala.io.Source
val source = Source.fromFile("path", "encode_format")//source本身就已经是iterator了,遍历它会得到一个个字符。也有fromURL, fromString
val lineIterator = source.getLines //getLines一旦调用,source的内容都被读取完了了,再调用会是empty-iterator。要重新调用,则再执行一次fromFile。也有mkString
source.close()

//写,可调用Java的PrintWriter
out = new PrintWriter(path)
out.println(content)

补充

package特性:

//一个class可以包含一个或多个包;一个包可以在不同的class中

//子包中的类可以访问夫包中的类,不需import

//绝对和相对包名
_root_.scala.collection....//绝对,平常用的都是相对,从最近的包去找,一旦有重名,就可能找不到实际想找的那个包

//可见性
package com.ibeifeng.scala
private[scala] def ... //表明在scala层可见

Actor

class HelloAcator extends Actor{
    def act(){
        while (true){
            receive{
                case name: String -> println...
            }    
        }
    }
}
val helloActor = new HelloActor
helloActor.start()
helloActor ! "leo" //发消息给Actor

val reply = actor !? message //同步,发送后马上得到返回值
val reply = future //手动获得返回值

lazy:用lazy定义的变量,只有在被调用时才创建

class Teat{
}
object Test1{
    def init(): Unit ={
        println("...")
    }
    
    def main(args: Array[String]): Unit = {
        val str = init()
        println("str")
        println(str)
    }
}
#结果为
...
str
()

遍历子目录

def getSubdirIterator(dir: File) : Iterator[File] = {
    val childDirs = dir.listFiles.filter(_.isDirectory)
    childDirs.toIterator ++ chidDirs.toIterator.flatMap(getSubdirIterator(_))
}

val iterator = getSubdirIterator(new File(path))

序列化和反序列化

@SeridalVersionUID(42L) class Person(val name : String) extends Serializable
val leo = new Person("leo")
//下面ObjectOutputStream的writeObject可以将类以序列化的形式写入文件
val oos = new ObjectOutputStream(new FileOutputStream(path))
oos.writeObject(leo)
oos.close
//下面是反序列化
val ois = new ObjectInputStream(new FileInputStream(path))
ois.readObject().asInstanceOf[Person]
restoredLeo.name

运行terminal命令

import sys.process._
"ls -l"!
"javac HelloWorld.java"!
"java HelloWorld"!

正则表达

val string = "xxxx"
val pattern = "[a-z]+".r//返回scala.util.matching.Regex
pattern.findAllIn(string)//返回迭代器。还有findFirstIn()第一个,直到不符合,replaceFirstIn(string, "replacement")

提取器

class Person(name: String, age: Int)
object Person{
    def apply(name: String, age: Int) = new Person(name, age)
    def unapply(str: String) = {
        val splitIndex = str.indexOf(" ")
        if (splitIndex == -1) None //返回结果只能一个?
        else Some((str.substring(0, splitIndex), str.substring(splitIndex +1)))
    }
}

object Person{
    def apply(name: String, age: Int) = new Person(name, age)
    def unapply(str: String) = Some(str)
}
Person("string", int)//创建一个object
val Person(n, a) = "k 2"//返回n: String = kaka 和 a: String = 2

注解

(scores.get("Leo"): @unchecked) match {case score => println(score)}//不检查类型是否匹配,直接得到什么打印什么
//如果要在主构造函数前加注解,需要加上一个圆括号

//开发注解
class Test extends annotation.Annotation
@Test//可以用了

//常用注解
@volatile var name = "leo" //不是百分百安全,线程在获取共享变量时,强制刷新该变量的值,让该值是最新的状态
@transient var name = "leo" //瞬态字段,不会序列化该字段
@SerialVersionUID(value) //标记类的序列化版本号,如果某类改变了,就要重新生成一个版本号,否则原先类的反序列化时会报错
@native //标记用c语言实现的本地方法
@throws(classOf[Exception]) def test(){} //相当于Java的throws
@varargs def test(args: String*) //表示方法接收变长参数
@BeanProperty //给JavaBean风格的类生成getter和setter方法
@BooleanBeanProperty //生成返回boolean的getter方法

XML

val books = <books><book>book1</book></books>  //返回scala.xml.Elem,也可写平级,返回NodeBuffer。有label/ child等方法

import scala.xml._
val booksBuffer = new scala.xml.NodeBuffer //得到上面空白的对象
val books: NodeSeq = booksBuffer //得到NodeSeq对象,可遍历

val books = <book id = "1">book1</book>
val id = books.attributes("id").text //取得上面id的值。books.attributes可遍历

//嵌入scala代码
val arr = Array("a", "b")
val books = <books>{arr(1)}</books>
val books1 = <books>{for (book <- arr) yield <book>{book}</book>}</books>
val books2 = <books id = {arr(0)}>book</books>
//修改元素
val books3 = books.copy(child = books.child ++ <book>book2</book>) //得到<books>b<book>book2</book></books>,由于上面books.child是b
//修改属性
val bk = <book id="1">book1</book>
val changed = bk % Attribute(null, "id", "200", Null)
//添加属性
val added = bk % Attribute(null, "id", "200", Attribute(null, "id2", "100", Null))
//加载和写入外部xml文件
val books = XML.load(new InputStreamReader(new FileInputStream(path), "UIF-8"))
posted @ 2018-10-29 17:22  justcodeit  阅读(300)  评论(0编辑  收藏  举报