Scala备忘录

本篇特用来对Scala的日常惯用法做一些记录,尽量简洁不废话。第三方包除外,只收录标准库。

 

  1. 集合类(Seq)
  2. 集合类(Map)
  3. 正则
  4. JSON解析
  5. XML解析
  6. 语法糖
  7. 杂项
  • 集合类(Seq) 最佳

- 构建

val truth = "fly" :: "is" :: "fun" :: Nil //List(fly,is,fun)
val list1 = List(1,2)
val list2 = List.fill(3)("one")  //List[String] =List(one,one,one)
val list3 = List.fill(3,2)(0)    //List[List[Int]] =List(List(0,0),List(0,0),List(0,0))
val list4 = List.range(9,1,-3)   //List[Int] =List(9,6,3)
val list5 = truth ::: list4      //List(fly,is,fun,9,6,3)
val list6 = truth ++ list4       //List(fly,is,fun,9,6,3)

- 分组 

truth.groupBy(_.length == 2)     //((List(is),List(fly,fun))
truth.grouped(2)                 //Iterator:List(fly,is),List(fun)
truth.sliding(2)                 //Iterator:List(fly,is),List(is,fun)
 - 截取 
truth.head           //fly
truth.tail           //List(is,fun)
truth.init           //List(fly,is)
truth.last           //fun
truth.drop(2)        //List(fun)
truth.dropRight(2)   //List(fly)
truth.takeRight(2)   //List(is,fun)
truth.takeWhile(_.charAt(0).toLowerCase!='I')   //List(fly)
truth.dropWhile(_.的charAt(0).toLowerCase!='I') //List(is,fun)
 - 过滤及计数 
truth.filter(s => s.length == 3) //List(fly,fun)
truth.find(_.charAt(0)=='A')     //None
truth.count(s => s.length == 3)  //2
 - 校验
truth.isEmpty                    //false
truth.forall(_.length> 2)        //false
truth.exists(_.charAt(0)=='i')   //true
truth.contains("is")             //true
truth.sameElements(List("fly","is","fun"))  //true
 - 添加序号 
truth.zipWithIndex       //List((fly,0),(is,1),(fun的,2))
truth.indices zip truth  //Vector((0,fly),(1,),(2,fun))
- 排序 
truth.sorted                              //List(fly,fun,is)
truth.sorted(Ordering[String].reverse)    //List(is,fun,fly)
truth.sortBy(x =>(x.toString.length, x))  //List(is,fly,fun)
truth.sortBy(x =>(x.toString.length, x))(Ordering[(Int,String)].reverse)  //List(fun,fly,is)
truth.sortWith(_.length - _.length < 0)   //List(is,fly,fun)
- 折叠
truth.foldRight("!")(_ + _)    // Flyisfun!
truth.reduceRight(_ + _)       // Flyisfun
truth.foldRight(List[String]()){(x,List)=>("<"+ x +">")::List}  //List(<fly>,<is>,<fun>)
truth.foldLeft("is")(_ + _)    //isflyisfun
List(1,2,3)reduceLeft(_ + _)   //6
 - 连接 - 展开
List.concat(List(),List('b'),List('c'))   //List(b,c)
truth.flatMap(_.toList)                   //List(f, l, y, i, s, f, u, n)
  
  • 集合类(Map) 最佳

--不可变

val map1 = Map("i" -> 1,"ii" -> 2)
map1 + ("vi" -> 6)  //Map(i -> 1, ii -> 2, vi -> 6)
map1 - "ii"         //Map(i -> 1)
map1 ++ List("iii" -> 3,"v" -> 5)  //Map(i -> 1, ii -> 2, iii ->3, v -> 5)
map1.getOrElse("vi",6)             //6

--可变

val map2 = scala.collection.mutable.Map.empty[String,Int]
map2 += ("one" -> 1) //Map(one - > 1)
map2 -= "one"        //Map()
map2 ++= Map("one" -> 1,"two" -> 2,"three" -> 3)  //Map(one -> 1, three -> 3, two -> 2)
map2 --= List("one","two")           //Map(three -> 3)
map2.getOrElseUpdate("one",100)      //Map(one -> 100, three -> 3)
map2.getOrElseUpdate("four",200)     //Map(one -> 100, three -> 3, four -> 200)
map2.transform((_,i)=> i + 1)        //Map(one -> 101, three -> 4, four -> 201)
  
  • 正则 最佳

--变量取值

val reg1 = new regex("""(\d{4})-(\d{2})-(\d{2})""")
val reg2 = """(\d{4})-(\d{2})-(\d{2})""".r
val reg1(year, month, day)="2016-12-13" //year:2016 month:12 day:13
"2016-12-13" match{
  case reg2(year,month,day) => (year,month,day)  //year:2016 month:12 day:13
  case _ => prIntln("not found!")
}
--名称取值
val reg3 =new Regex("""(\d{4})-(\d{2})-(\d{2})""","year","month","day")
reg3.findAllIn("2016-12-13 american tv 2017-11-14").foreach(println)
val m1 = for (r <- reg3.findAllMatchIn("abc 2016-12-13 american tv 2017-11-14")) yield r.group("year")
println(m1.toList)    //List(2016, 2017)
--序号取值
val m2 = for (r <- reg3.findAllMatchIn("abc 2016-12-13 american tv 2017-11-14")) yield r.group(2)
println(m2.toList)    //List(12, 11)
   
  • JSON解析 最佳

【说明】2.11以后的jar包需单独下载 https://github.com/scala/scala-parser-combinators

val jsonStr=  """ {"subjects":[
  {"title":"孤单又灿烂的神:鬼怪", "rate":"9.1", "id":"26761935"},
  {"title":"西部世界第one季",   "rate":"9.0", "id":"2338055"}] }"""

//一次性使用可以用 asInstanceOf做类型转换,转换后为List,Map,和数组的混合体
val map= JSON.parseFull(jsonStr).get.asInstanceOf [Map[String,List[Map[String,String]]]]
val list = (for (m <- map("subjects")) yield List(m("id"), m("title"), m("rate")))
println(list)    //List(List(26761935, 孤单又灿烂的神:鬼怪, 9.1), List(2338055, 西部世界第one季, 9.0))

//需要异常处理的场合使用模式匹配
val map2 = JSON.parseFull(jsonStr) match {
  case m: Map[String,List[Map[String,String]]] => m
  case _ => //todo 异常处理如: println("解析失败:"+ jsonStr)
}
  
  • XML解析 最佳

【说明】2.11以后的jar包需单独下载https://github.com/scala/scala-xml

--构建

val elem1 = scala.xml.XML.loadString("<HTML> </HTML>")
val elem2 = scala.xml.XML.loadFile("1.XML")
val (name, age)=("James",10)
val elem3 = <html>name={name},age={age}</html>
val elem4 = <r>{(1 to 5).map(i => <e>{i}</e>)}</r>
         // <r><e>1</e><e>2</e><e>3</e><e>4</e><e>5</e></r>

--节点抽取

val elem  = <uu><u name ="aa"/><u name ="bb"/><u name ="cc"/></uu>
val name1 = (elem \"u")(0)\"@name"      //aa
val name2 = elem \"u"\\"@name"          //aa bb cc

elem match{
  case <uu>{uAll @ _*}</uu> =>
    for(u <- uAll) println(u \ "@name") //aa bb cc
  case _ => "no match!"
}

val xml=
<shopping>
  <item name="bread" quantity="3" price="2.50"/>
  <item name="milk"  quantity="2" price="3.50"/>
</shopping>
(for(item <- xml\"item";
       p = (item\"@price").text.toDouble;
       q = (item\"@quantity").text.toInt)
yield (p*q)).map(println)

--XML输出

val pp = new scala.xml.PrettyPrInter(80,4)    //行宽80,缩进4
prIntln(elem)                    //直接输出
prIntln(pp formatNodes elem)     //格式化输出
  
  • 语法糖最佳

// 观察语法糖对理解Scala内部的实现非常必要,使用这个命令 scala -Xprint:typer test.scala

// case class 语句会自动给类中添加 equals/ hashCode/ toString/ copy/ apply/ unapply 等方法

// 特别是 apply 用于 类名() 语法生成对象(不使用new!)

// 而 unapply 用于模式匹配时项目的抽取

case class People( name: String, age: Int);
val p = People("zhangshan",20)
p match {
  case People(name,age) => println(name,age)
}

 

// for 语句会变换成 foreach(foreache...))

// for-yield 会变换成  flatMap(flatMap(...map()))      注意最后一级为map

// for 语句中含有if 则会转换成 withFilter()调用

val (f1,f2,f3) = (Future{1}, Future{1}, Future{1})
for{  a <- f1;  b <- f2;  c <- f3 } yield a+b+c

// lazy变量,背后的实现是个典型的双重检测锁(DCL)模式

 

  • 杂项 最佳

- 任意数生成

//生成[0,N)的任意数 - 同java.util.Random中
Random.nextInt(99999)
//生成任意5位字母数字
Random.alphanumeric.take(5).mkString

猜你喜欢

转载自duanhengbin.iteye.com/blog/2344820