scala笔记

1.创建Array
// array 创建方法1
val arr = new Array[String](3)
arr(0) = "1"
arr(0) = "x"
//底层调用 def update(i: Int, x: T) { throw new Error() }
arr(1) = "1"
arr(2) = "2"
println(arr.mkString(","))
//x,1,2
// array 创建方法2
val arr2 = Array("x","y","z")
println(arr2.mkString(","))
//x,y,z
2.list
 
//创建列表
val oneTwo = List(1, 2)
val threeFour = List(3, 4)
//将oneTwo 中的元素全部加到threeFour 前部
val oneTwoThreeFour = oneTwo ::: threeFour
val twoThree = List(2, 3)
//:: 是右操作数twoThree 的方法
val oneTwoThree = 1 :: twoThree
 
//list 的常用方法
oneTwoThreeFour.count(_ % 2 == 0) //统计偶数的数量
oneTwoThreeFour.drop(2) //返回丢弃前两个元素的list
oneTwoThreeFour.exists(_ == 2) // 是否存在元素2
oneTwoThreeFour.filter(_ % 2 != 0) //过滤出奇数
oneTwoThreeFour.forall(_ % 2 == 0) //list中是否全是偶数
oneTwoThreeFour.head // list 第一个元素
oneTwoThreeFour.tail// 返回除第一个元素的其他元素组成的list
oneTwoThreeFour.init//除最后一个元素的list
oneTwoThreeFour.last// 最后一个元素
oneTwoThreeFour.reverse //list 反转
oneTwoThreeFour.sortWith((x, y) => x < y) //list 排序
list一经创建就不可变,里面的值也不可变
list 不提供append 方法,因为随着列表长度的增加,append 方法(会不断的创建的新数组,复制上一个列表的值进去)的操作时间呈线性增长,而 :: 方法的时间是固定的
3.元组
val tp = (1,2,"salary")
println(tp._2)
元组中可以存放不同类型的元素,(1,2,"salary") 存放了(int,int,String)类型的值,可以用于返回不同类型组合的返回值。
为什么不用 tp(0) 这种方式取值?因为tp中的每个元素的类型不是固定的
4.set and map
 
val set = Set(1, 2, 3, 5) //不可以调用 += 方法,除非将set 声明为var
val set2 = scala.collection.mutable.Set.empty[Int]
set2 += 1
set2 += 2
set2 ++= set
println(set2)
//Set(1, 5, 2, 3)
val map = Map("x" -> 1, "z" -> 2)
val map2 = scala.collection.mutable.Map.empty[String, Int]
map2 += "x" -> 1
map2 += "y" -> 2
map2 ++= map
println(map2)
//Map(z -> 2, y -> 2, x -> 1)
 
5.读取文件
 
val lines = Source.fromFile(filename).getLines().toList //如果不调用toList 方法,则返回的是 Iterator ,只能遍历一遍
val line = lines.reduceLeft((x, y) => if (x.length > y.length) x else y)
println(line)
println("=" * 30)
lines.foreach(println)
 
Michael, 15
==============================
Michael, 15
Andy, 30
Justin, 19
 
6.scala 中定义副作用方法
通常scala用如下方式定义带副作用的方法,类似java中的方法定义,这样的定义默认返回值类型是Unit,因此函数末尾虽然写了 "s" ,s也会被转化为Unit
 
def sideEffectFunc(s: String) {
  println(s)
  s
}
 
7.scala 的每个源文件都隐含了对包java.lang、 包scala,以及单例对象Predef的成员的引用,PreDef 包含了许多有用的方法,例如println 语句 实际调用了 Predef 的  def println(x: Any) = Console. println (x),可以看到它又调用了Console。println(x) 方法
8.App 特质,继承App 可以省去很多代码编写工作,不必编写main类,就可直接运行
 
import scala.App
 
object Test2 extends App {
  println("jaosn")
}
 
9.scala 对象相等性比较
scala 中 "==" 与java 中的 equal 类似,比较的是对象的内容,eq  ne 比较的是对象的引用地址是否相同
"==" 比较逻辑:先看左操作数是否为null ,若不是null 则调用左操作数的 equal 方法比较,因此scala 可以省去判断是否为null
 
10.
scala 编译器会把类内部既不是字段也不是方法定义的代码编译 到 主 构造器中
 
11.scala 里每个辅助构造器的第一个动作都是调用同类的别的构造器(包括主构造器),即都是以 this(……)开始的,也就是说每个构造器调用终将结束于对主构造器的调用,因此主构造器是类的唯一入口
 
12.scala中的常量,习惯命名方式是驼峰命名法,首字母大写 比如:MaxValue
 
13.一个案例
class Rational(n: Int, d: Int) {
  require(d > 0)
  private val g = gcd(n.abs, d.abs)
  val numer = n / g
  val denom = d / g
 
  def this(i: Int) = this(i, 1)
 
  def +(that: Rational): Rational = new Rational(numer * that.denom + that.numer * denom, denom * that.denom)
 
  def -(that: Rational): Rational = new Rational(numer * that.denom - that.numer * denom, denom * that.denom)
 
  def *(that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom)
 
  def /(that: Rational): Rational = new Rational(numer * that.denom, denom * that.numer)
 
  override def toString: String = {
    if (denom == 1) s"$numer" else s"$numer / $denom"
  }
 
  private def gcd(a: Int, b: Int): Int = {
    if (b == 0) a else gcd(b, a % b)
  }
}
 
object Rational {
  def main(args: Array[String]): Unit = {
    //隐式转换,解释器会自动将int 类型转换为Rational
    implicit def intToRational(i: Int): Rational = {
      new Rational(i)
    }
 
    val r = new Rational(2, 3)
    println(4 + r)
    println(r + 4)
  }
}
 
14.scala 中的赋值语句返回值为 Unit ,因此 while ((line = in.readLine())!= "") 永远返回true
15.带过滤器的for
 
for (i <- 1 to 10 if i % 2 == 0; if i != 4) {
  println(i)
}
16.for嵌套循环
 
for (i <- 1 to 9 ;j <- 1 to i) {
  print(s" $j * $i = ${i*j} ")
  if(i==j) println()
}
17.yield 表达式
 
val seq = for (i <- 1 to 10) yield {
  val j = if (i % 2 == 0) i * 2 else i * 3
  i * j
}
 
18.try catch 捕获异常
try{
  val file = new File("aa")
}catch {
  case ex:FileNotFoundException => println("aa not exists")
  case ex => ex.printStackTrace()
}
19.带返回值的try catch
 
def getUrl(url: String) = try {
  new URL(url)
} catch {
  case ex => new URL("www.baidu.com")
}
20.重复参数
 
def echo(args: String*): Unit = {
  args.foreach(println)
}
可以将方法的最后一个参数定义为重复参数,方法是再类型后加 * ,实际上atgs* 类型是 Array[String],但是传参的时候却不能传 数组 ,比如:val arr = Array("a","b");echo(arr),此时会报错,正确的写法是 echo(arr:_*)
 
21.scala.util.Try
def testTry(): Unit ={
  val tt = Try(24/2)
  tt match {
    case Success(a) => println(a)
    case Failure(a) => a.printStackTrace()
  }
}
 
22.抽象类
 
abstract class Element {
  def contents: Array[String]
}
抽象类class 关键字前必须带有  abstract ,不带 = 和方法体的方法即为抽象方法,抽象方法不用带 abstract
 
23.访问字段值比调用方法略快,因为字段值在类初始化时就已经预先计算,而方法在每次调用时都要计算,但是字段值占用的空间略大
24.scala 建议将没有参数且不带副作用的方法定义成无参数方法风格(不带括号的方法),将不带参数但是有副作用的方法定义成空括号方法。千万不要将不带参数且有副作用的方法定义成无参数方法风格,午餐方法的访问类似访问属性,客户会奇怪,为什么这个属性具有副作用
 
25.继承
 
class ArrayElements(conts: Array[String]) extends Element {
  override def contents: Array[String] = conts
}
继承表示超类的所有的成员都属于子类,以下两种情况除外,1.超类的私有成员,2.被子类重写的超类成员
scala 中如果超类的成员是具体,非抽象的,子类重写该成员时必须加override 关键词,如果是抽象的,则可加可不加
 
26.如果属性或方法不希望子类重写,则可以加final 关键字,如
 
final def height: Int = contents.length
 
27.scala 继承建议:将子类写在抽象类的伴生对象中,并定义为private,抽象类伴生对象中定义创建子类的工厂方法
28.scala 的根类是Any
Any 有两个子类:AnyVal 和AnyRef,AnyVal 是每个内建值类的父类,有9个这样的值类,Byte,Short,Char,Int,Long,Float,Double,Boolean,Unit,前八个对应了java的八个基本类型,运行时会转换成java的八大基本类型,他们不能用new I创建,因为他们时abstract 且是final的
第九个 是 Unit,相当于是java中的void,它的值是 “()”,
AnyRef 是所有引用类的基类
 
28.scala.Null 是null引用对象的类型,它是每个引用类(继承自AnyRef)的子类,null 不兼容值类型。Nothing 位于scala 层级的最底层,是任何其他类型的子类型,Nothing类型没有任何值,Nothing 通常用于不正常的终止,比如error
 
29.trait的使用,除了以下两点外,与类的使用无别
1)特质不能有“类”参数, 比如 trait Foo(i:Int){} ,编译会报错
2)在类中super 调用是静态绑定的,而在trait中super 的调用是动态绑定的,在定义特质的时候,super调用方法的实现尚未被定义
 
30. Ordered 特质
在开发中我们经常要用到比较,比较无非 <,> ,<= ,>=不管哪个类,这四种比较的逻辑都不会改变,scala 提供了Ordered特质来帮助类实现比较,我们唯一要做的就是混入 Ordered[C] 特质(C 是要比较的类),让后实现compare 方法,this < that 则返回 <0 的值,相等返回 0,
 
31.特质的堆叠使用
 
package com.program
 
import scala.collection.mutable.ArrayBuffer
 
abstract class IntQueue {
  def get: Int
 
  def put(i: Int)
 
  def hasNext: Boolean
}
 
class BasicIntQueue extends IntQueue {
  private val queue = new ArrayBuffer[Int]()
 
  override def get: Int = queue.remove(0)
 
  override def put(i: Int): Unit = {
    println(s"i 的值是:$i")
    queue += i
    println(s"值添加完毕")
  }
 
  override def hasNext: Boolean = {
    queue.size > 0
  }
}
 
trait Doubling extends IntQueue {
  abstract override def put(i: Int): Unit = {
    println(s"double 前 ")
    super.put(i * 2)
    println(s"double 后 ")
  }
}
 
trait Incement extends IntQueue {
  abstract override def put(i: Int): Unit = {
    println(s"increment 前 ")
    super.put(i + 1)
    println(s"increment 后 ")
  }
}
 
trait Filter extends IntQueue {
  abstract override def put(i: Int): Unit = {
    println(s"filter 前")
    if (i > 0) super.put(i)
    println(s"filter 后")
  }
}
 
class Foo1 {
  def foo(): Unit = {
    println("foo1")
  }
}
 
class Foo2 extends Foo1 {
  override def foo(): Unit = {
    println("foo2 前")
    super.foo()
    println("foo2 后")
  }
}
 
class Foo3 extends Foo2 {
  override def foo(): Unit = {
    println("foo3 前")
    super.foo()
    println("foo3 后")
  }
}
 
object Test2 extends App {
  val myqueue = new BasicIntQueue with Doubling with Incement with Filter
  myqueue.put(1)
  myqueue.put(1)
  myqueue.put(2)
  while (myqueue.hasNext) {
    println(myqueue.get)
  }
 
  println("=" * 20)
  val foo = new Foo3
  foo.foo()
}
 
filter 前
increment 前
double 前
i 的值是:4
值添加完毕
double 后
increment 后
filter 后
filter 前
increment 前
double 前
i 的值是:4
值添加完毕
double 后
increment 后
filter 后
filter 前
increment 前
double 前
i 的值是:6
值添加完毕
double 后
increment 后
filter 后
4
4
6
==================== 
foo3 前
foo2 前
foo1
foo2 后
foo3 后
由输出结果可知特质的堆叠是从最右侧的特质开始的
32.样本类
case class Foo(i:Int)
scala 编译器会自动为样例类添加一些便捷设定:
1)自动添加与类名一致的工厂方法,所以可以用 Foo(1) 来创建Foo 对象
2)样例类的参数列表里的参数隐式添加了 val,这些参数会作为样例类的属性存在
3)编译器为样例类添加了 toString,hashCode和equal 的“自然”实现
 
33.封闭类
一旦你写了模式匹配,就得保证考虑到了所有可能的情况,否则程序就会报错,scala 提供了一种检查机制,可以将超类封闭起来,这样在编译时scala 会自动检查所有的匹配可能,但是,你必须把所有子类定义在存放超类的文件中,并在超类前加上 sealed,如下
 
package com.program
sealed abstract class Animal
case class Fish(sound:String) extends Animal
case class Bird(sound:String) extends Animal
case class Horse(sound:String) extends Animal
 
object Sealtest {
  def main(args: Array[String]): Unit = {
    val animal:Animal = Fish("gulu")
    val sound = animal match {
      case Fish(x) => x
    }
  }
}
如上代码编译时会有如下提示:
 
Warning:(10, 17) match may not be exhaustive.
It would fail on the following inputs: Bird(_), Horse(_)
    val sound = animal match {
如果不希望编译器进行检查,可以加上(animal:@unchecked)match  ,实测不好用,scala 无法识别(sclaal 版本2.11.8)
 
  val list = List(1, 2, 3)
    list match {
      case e@List(_*) => println(e) //List(1, 2, 3)  能把e所代表的变量取到
    }

 

 
34.list 类
 
package com.program
 
object ListSuite {
  //插入排序,xs 已经是排序的
  def insert(x: Int, xs: List[Int]): List[Int] = {
    if (xs == Nil || x < xs.head) {
      x :: xs
    } else {
      xs.head :: insert(x, xs.tail)
    }
  }
 
  //对list 排序,list 的元素是无序的
  def isort(xs: List[Int]): List[Int] = xs match {
    case Nil => Nil
    case head :: tail => insert(head, isort(tail))
  }
 
  def main(args: Array[String]): Unit = {
    //插入排序
    var list = List(2)
    list = insert(1, list)
    list = insert(3, list)
    list = insert(4, list)
    list = insert(5, list)
    println(list) //List(1, 2, 3, 4, 5)
    //插入排序
 
    //随机列表排序
    val list2 = List(3, 4, 1, 2, 6)
    println(isort(list2)) //List(1, 2, 3, 4, 6)
    //随机列表排序
    //列表模式
    val listFruit = List("apple", "banana", "orange")
    val List(apple, banana, orange) = listFruit
    println(apple) // apple
    val x :: rest = listFruit
    println(x) // apple
    //列表模式
 
    //llist 一阶方法
    //列表拼接
    val listconcat = list ::: list2 //List(1, 2, 3, 4, 5, 3, 4, 1, 2, 6)
    //获取列表的长度,会遍历列表的每一个元素,耗时,如果只需得知列表是否为空,可以调用listconcat.isEmpty
    listconcat.length
 
    //列表反转
    println(list.reverse) //List(5, 4, 3, 2, 1)
    println(list.take(2)) //List(1, 2)
    println(list.drop(2)) //List(3, 4, 5)
    println(list.splitAt(2)) //(List(1, 2),List(3, 4, 5))
 
    println(list(2)) //获取list 的index 为2的元素,等价于 list.drop(2).head,所以比较耗时
    println(list.indices) //Range(0, 1, 2, 3, 4)  索引值组成的列表
 
    println(list.zip(list2)) //List((1,3), (2,4), (3,1), (4,2), (5,6))
    println(list.zipAll(9 :: list2, 2, 3)) //List((1,9), (2,3), (3,4), (4,1), (5,2), (2,6))
 
    println((list.zip(list2)).unzip) //(List(1, 2, 3, 4, 5),List(3, 4, 1, 2, 6))
 
    println(list.partition(_ % 2 == 0)) //(List(2, 4),List(1, 3, 5))
 
    println(list.find(_ % 2 != 0)) //返回第一个满足条件的元素
 
    println(list.takeWhile(_ % 2 != 0)) //List(1) 返回满足条件的最长序列
    println(list.dropWhile(_ % 2 != 0)) // List(2, 3, 4, 5)
    println(list.span(_ % 2 != 0)) // (List(1),List(2, 3, 4, 5))  takeWhile and dropWhile 的组合
 
    println(list.exists(_ % 2 == 0)) //true
    println(list.forall(_ % 2 != 0)) //false
 
    val max = (0 /: list) ((x, y) => if (x > y) x else y)
    println(max) //5
 
    val min = (list :\ 0) ((x, y) => if (x < y) x else y)
    println(min) //0
 
    println(List.fill(5)("a")) //List(a, a, a, a, a)
    
  }
}
 
 
 
35.泛型,上界,下界,协变,逆变
 
37 如果想在列表尾部追加元素,可以使用高效的listBuffer,使用listBuffer 还可以避免堆栈溢出
 
val lb = new ListBuffer[Int]
lb += 1
lb += 2
println(lb) //ListBuffer(1, 2)
 
38.如果需要可变长的数组,可以使用ArrayBuffer,除了与array相同的操作外,还增加了首位添加,删除操作
 
val ab = new ArrayBuffer[Int](10)
ab += 1
ab += 2
ab.remove(0) // 1 有返回值
39.如果需要先进先出的序列,可以使用queue,queue分为两种,一种是可变队列,一种是不可变队列
 
 
val que = Queue(0)  不可变
val que2 = que.enqueue(1)
val que3 = que2.enqueue(List(2,3,4))
println(que3) //Queue(0, 1, 2, 3, 4)
println(que3.dequeue) //(0,Queue(1, 2, 3, 4))
 
val mque = collection.mutable.Queue(0)
mque += 1
mque += 2
println(mque) //Queue(0, 1, 2)
println(mque.dequeue()) //0
 
 
40.若需要先进后出的序列,可以使用stack,stack 也有可变和不可变的
 
val stack = collection.mutable.Stack(0)
stack.push(1)
stack.push(2)
println(stack) //Stack(2, 1, 0)
println(stack.top)//2
println(stack.pop())//2
println(stack)//Stack(1, 0)
 
41.set 基本操作
 
var set = Set(1,2)
set += 5
set -= 1
set ++= List(3,4,5)
set --= List(2,3)
println(set)
println(set.intersect(Set(5,6))) //交集
 
42.map的基本操作
 
val map = collection.mutable.Map.empty[String, Int]
map += "a" -> 2
map += "a" -> 2
map += "a" -> 2
map("b") = 3
map ++= List("c" -> 3, "d" -> 4)
map --= List("a", "b")
println(map.keys) //iterator
println(map.values) //iterator
println(map.keySet) //set
println(map)
可变map 和不可变map的相互转换 
 
scala.collection.mutable.HashMap.empty[Int, Int] ++ Map(1 -> 1)
Map.empty[Int, Int] ++ collection.mutable.HashMap(1 -> 1)
 
43.默认的集和映射
scala.collection.mutable.Set  工厂方法默认返回: scala.collection.mutable.HashSet
scala.collection.mutable.Map  工厂方法默认返回: scala.collection.mutable.HashMap
 
不可变集合的工厂方法返回对象比较复杂;
set
map
 
44.将类的主构造器设置为私有的
将无法通过主构造器创建实例,但是如果有辅助构造器,依然可以使用辅助构造器创建实例
 
class Queue[T] private (val lead: List[T], val tail: List[T])
45.信息隐藏,不向用户暴漏代码实现细节
方案一:
class Foo private(val a:Int,val b:Int)
object Foo{
def apply(a:Int,b:Int) = new Foo(a,b)
}
 
方案二:
trait Foo{
val a:Int
val b:Int
}
 
object Foo{
def apply(...) = new FooSub(...)
private class FooSub extends Foo{
....
}
}
 
推荐使用方法二
 
46.为什么要用type
理由之一:提供一个类型的别名,可以避免冗长的类型名字
 
47.一个例子
package com.program
 
class AbstractTest() extends Ft {
  val a = 3
}
 
 
trait Ft {
  val a: Int
  require(a > 0)
}
 
object AbstractTest {
  def main(args: Array[String]): Unit = {
    println(new AbstractTest().a)
  }
}
 
Exception in thread "main" java.lang.IllegalArgumentException: requirement failed
    at scala.Predef$.require(Predef.scala:212)
    at com.program.Ft$class.$init$(AbstractTest.scala:10)
    at com.program.AbstractTest.<init>(AbstractTest.scala:3)
    at com.program.AbstractTest$.main(AbstractTest.scala:15)
    at com.program.AbstractTest.main(AbstractTest.scala)
 
运行为何回报错,因为 AbstractTest 在初始化之前,先要初始化父类,此时val a 还未被初始化,所以报错
改成下面的写法就可以了
class AbstractTest(val a: Int) extends Ft {
 
}
 
48.枚举简单使用
package com.program
 
object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon = Value("1")
  val Tue = Value("2")
  val Wed = Value("3")
  val THu = Value("4")
  val Fri = Value("5")
  val Sat = Value("6")
  val Sun = Value("7")
 
  def checkExists(day: String): Boolean = {
    this.values.exists(_.toString == day)
  }
 
  def isWorkDay(day: WeekDay): Boolean = {
    !(day == Sat || day == Sun)
  }
 
  def showAll = this.values.foreach(println)
}
 
object EnumTest {
  def main(args: Array[String]): Unit = {
    println(WeekDay.checkExists("8"))
    println(WeekDay.Sun == WeekDay.withName("7"))
    println(WeekDay.Sun == 7)
    WeekDay.showAll
    println(WeekDay.isWorkDay(WeekDay.Sat))
  }
}
49.scala and xml
package com.program
 
import scala.xml.dtd.DocType
 
object XMLTest {
  def main(args: Array[String]): Unit = {
    //xml 字面量
    val hw = <a>
      {"hello" + ", world"}
    </a>
    println(hw)
    val num = 100 //<a>hello, world</a>
 
    val node = <a>{if (num > 100) <num>{num}</num> else xml.NodeSeq.Empty}</a>
    println(node) //<a></a>
 
 
    //推荐使用xml字面量,请看下面两个例子
    println(<a>
      {"</a>可能存在危险"}
    </a>)
    //若使用低级字符串,则容易造成类似sql注入的结果
    println("<a>" + "</a>可能存在危险" + "</a>")
 
    //xml 序列化
    val stu = new Student {
      override val name: String = "jason"
      override val tel: String = "1345"
      override val addr: String = "sh"
      override val age: Int = 27
    }
    val stuXml = stu.toXml
    println(stuXml)
    /*<student>
      <name>jason</name>
      <age>27</age>
      <addr>sh</addr>
      <tel>1345</tel>
    </student>*/
 
    //如果想在xml文本中包含 {} 则可以用{} 转义
    val x = 23
    println(<a>{{{x}}}</a>) //<a>{23}</a>
 
    //xml 拆解
    val n3 = <a namea="na">a<b nameb="nb">b<c>c</c></b></a>
    println(n3.text) //abc
    println(n3 \ "b") //<b>b<c>c</c></b>
    println((n3 \ "b").text) //bc
    println(n3 \ "c") // "" 空字符串
    println(n3 \\ "c") //<c>c</c>    两个斜杠代表深度搜索
    println(n3 \\ "@nameb") // nb 获取标签的属性
 
    //xml 反序列化
    val stu2 = stu.fromXml(stuXml)
    println(stu2)
 
    //xml 的存储与加载
    xml.XML.save("stu.xml", stuXml, "utf-8", true, null)
    xml.XML.loadFile("stu.xml")
 
    //xml 与模式匹配
    def proc(node: xml.Node): String = node match {
      case <a>{contents}</a> => s"it is an a : ${contents}"
      case <b>{contents}</b> => s"it is a b : ${contents}"
      case _ => s"it is something else"
    }
 
    println(proc(<a>apple</a>)) //it is an a : apple
    //proc 目前只能进行单个子节点的匹配 ,如果要匹配出以下内容,可以用proc2方法
    println(proc(<b>a<em>yellow</em>banana</b>))//it is something else
    println(proc(<o>orange</o>))//it is something else
 
    def proc2(node:xml.Node):String = node match {
      case <b>{contents @ _*}</b> => s"it is b ${contents}"
      case _ => s"it is something else"
    }
 
    println(proc2(<b>a<em>yellow</em>banana</b>))//it is b ArrayBuffer(a, <em>yellow</em>, banana)
 
    //模式匹配与for
 
    val n4 =
      <students>
        <student>
          <name>jason</name>
          <age>25</age>
          <addr>sh</addr>
          <tel>123</tel>
        </student>
      </students>
    println("=================")
    n4 match {
      case <students>{students @_*}</students> =>
        for(student <- students){
          println((student \ "name").text)
        }
      case _ => println("nothing")
    }
    println("=================")
    /*=================
 
    jason
 
    =================*/
    println("<<<<<<<<<<>>>>>>>>>")
    n4 match {
      case <students>{students @_*}</students> =>
        for(student @ <student>{_*}</student> <- students){
          println((student \ "name").text)
        }
      case _ => println("nothing")
    }
    println("<<<<<<<<<<>>>>>>>>>")
    //<student>{_*}</student> 限制了for 表达式的枚举
    /*<<<<<<<<<<>>>>>>>>>
    jason
    <<<<<<<<<<>>>>>>>>>*/
  }
}
 
abstract class Student {
  val name: String
  val age: Int
  val addr: String
  val tel: String
 
  def toXml =
    <student>
      <name>{name}</name>
      <age>{age}</age>
      <addr>{addr}</addr>
      <tel>{tel}</tel>
    </student>
 
 
  def fromXml(node: xml.Node): Student = {
    new Student {
      override val name: String = (node \ "name").text.trim
      override val tel: String = (node \ "tel").text.trim
      override val addr: String = (node \ "addr").text.trim
      override val age: Int = (node \ "age").text.trim.toInt
    }
  }
 
  override def toString = s"Student($name, $age, $addr, $tel)"
}
 
50.scala 中的equals 方法,最好与hashcode 一起重写
class Foo11(final val x: Int, final val y: Int) {
 
  override def hashCode(): Int = Objects.hash(new Integer(x), new Integer(y))
 
  override def equals(obj: scala.Any): Boolean = obj match {
    case that: Foo11 => (that canEqual (this)) && that.x == this.x && that.y == this.y
    case other => false
  }
 
  def canEqual(other: Any): Boolean = other.isInstanceOf[Foo11]
}
 
class Goo11(x: Int, y: Int, val z: Int) extends Foo11(x, y) {
 
  override def hashCode(): Int = super.hashCode() + Objects.hash(new Integer(z))
 
  override def equals(obj: Any): Boolean = obj match {
    case that: Goo11 => (that canEqual this) && super.equals(that) && that.z == that.z
    case other => false
  }
 
  override def canEqual(other: Any): Boolean = other.isInstanceOf[Goo11]
}
 
51.akka
 52.Option 的一些用法
    val mapx = Map("name" -> "jason", "age" -> "?")
    val s: String = null
    val a = Option(s).orElse(mapx.get("name")).orNull
    println(a) //jason
    println(Option("TOM").map(_.toLowerCase)) //Some(tom)

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

转载于:https://www.cnblogs.com/jason-dong/p/10242533.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值