
//这是单行注释
/*
这是多行注释
*/
/**
这是文档注释
*/
变量声明:var 变量名:类型 = 初始值
常量声明:var 变量名:类型 = 初始值
Scala中可以不写 ; --->一般情况我们都不写,因为;本来就对代码没有什么意义;
Scala中有自动类型推断,所以一般情况都可以省略,故可以写成如下方式。
变量声明:var 变量名 = 初始值
常量声明:var 变量名 = 初始值
在函数式编程中,能用常量就用常量,因为多线程中变量会引起线程安全问题。

()null和Java一样,Scala也分自动类型转换和强制类型转换
自动类型转换规则和Java一样,都是从范围小类型转换到范围大类型
强制类型转换和Java不一样,Scala是调用方法的方式来完成转换
object Demo {
  def main(args: Array[String]): Unit = {
    //强制类型转换
    val a = 10
    println(a.toDouble)//10.0
    /**
      *自动类型转换
      * byte->short->int->long->float->double
      *        char->int->long->float->double
    */
    val b:Double = 10
    println(b)//10.0
    // 如下这种自动类型转换会失败,因为不能自动类型转换不能大转小
    // val c:Int = 10.0
  }
}
object Demo1 {
  def main(args: Array[String]): Unit = {
    //name = zhangsan,age = 10 sal = 50.56
    printf("name = %s,age = %d sal = %.2f", "zhangsan", 10, 50.55555)
    //name = lisi,age = 30
    val name = "lisi"
    val age = 20
    println(s"name = ${name},age = ${age + 10}")
    /**
      * a
      * b
      * c
      */
    val s =
      """
        |a
        |b
        |c
      """.stripMargin
    println(s)
  }
}
Scala中没有三元运算符,只能使用If Else来实现其功能,写法和Java一样
Scala中没有switch
Scala中,任何语法结构都有类型和值,返回最后一行代码的值。如If Else,赋值语句,代码块等等
Scala中 == 等价于Java中的equals()方法,eq 等价于Java中的 ==
object Demo2 {
  def main(args: Array[String]): Unit = {
    var i = 1
    if (true) {
      i = 2
    } else {
      i = 0
    }
    //2
    println(i)
  }
}
object Demo3 {
  def main(args: Array[String]): Unit = {
    val func = if (true) {
      1
      2
    } else {
      0
    }
    //2
    println(func)
  }
}
object Demo4 {
  def main(args: Array[String]): Unit = {
    val func = if (true) {
    }
    //()
    println(func)
  }
}
while和do while和Java一样
for不像Java,其实是一种遍历
object Demo5 {
  def main(args: Array[String]): Unit = {
    var i = 1
    while (i < 5) {
      println(i)
      i += 1
    }
  }
}
object Demo6 {
  def main(args: Array[String]): Unit = {
    var i = 1
    do {
      println(i)
      i -= 1
    } while (i > 1)
  }
}
object Demo7 extends App {
  //遍历序列
  for (x <- "123456") {
    println(x)
  }
  //间隔,反转:打印10到1,并且间隔2个打印
  for (y <- 1.to(10, 2).reverse) {
    println(y)
  }
  //循环守卫:打印1到10的偶数
  for (z <- 1.to(10) if z % 2 == 0) {
    println(z)
  }
  //for推到:使循环可以返回最后的值,如下1到10的平方
  val a = for (z <- 1.to(10)) yield z * z
  println(a)
}
import scala.util.control.Breaks._
object Demo8 extends App {
  //退出循环
  breakable(
    for (x <- 1.to(10)) {
      if (x == 5) break()
      println(x)
    }
  )
}
函数式编程强调执行的结果而非执行过程,倡导利用若干简单的单元让计算结果不断演进,逐层推到复杂运算,而不是设计一个复杂的运算过程。
在Scala中,函数也是一个对象,会有返回值,可以作为值传递给另外的函数。
函数的定义: def 函数名(参数1:参数1类型,参数2:参数2类型):函数返回值 = { 代码块 }
函数返回值是可以自动推到的: def 函数名(参数1:参数1类型,参数2:参数2类型)= { 代码块 }
函数形参都是val常量
纯函数
不能产生副作用
引用透明
  //纯函数
  def add(a: Int, b: Int): Unit = {
    a + b
  }
      
 //纯非函数 
 def add1(a: Int, b: Int): Unit = {
    //破坏了纯函数,产生副作用
    println("打印功能")
    a + b
  }
     
 //纯非函数      
  var x = 0;
  def add2(a: Int, b: Int): Unit = {
    //破坏了纯函数,产生副作用
    x = 100
    a + b
  }
  var x = 1;
  def add(a: Int, b: Int)= {
    //破坏了纯函数
    a + b + x
  }
  println(add(1, 2))    //4
  x = 10
  println(add(1, 2))    //13
参数类型*为可变形参,传入一个序列中的每个元素。
  def add(a: Int*) = {
    a.sum
  }
  println(add(1, 2, 3))    //6
      
  def add(a: Int*) = {
    a.sum
  }
  val arr: Range.Inclusive = 1.to(3)
  println(add(arr: _*)) //6  序列展开需要使用: _*
      
  def myconcat(x: String, pre: String = "<html>", suf: String = "</html>") = {
    pre + x + suf
  }
  //<html>abc</html>
  println(myconcat("abc", "<html>", "</html>"))
  println(myconcat("abc"))
  println(myconcat("abc", suf = "</html>"))
同Java处理方式,有点小不同
import java.io.{FileInputStream, FileNotFoundException}
object Demo9 extends App {
  //在Java中FileNotFoundException属于编译时异常,必须处理,而Scala可以不处理,发生直接抛
  //new FileInputStream("")
  //java.io.FileNotFoundException:
  //处理完毕
  try {
    new FileInputStream("")
  } catch {
    case e: FileNotFoundException => println(e)
  }finally {
    println("处理完毕")
  }
}
Scala object相当于java中的单例,object中定义的全是静态的,相当于java中的工具类,Object默认不可以传参,对象要传参,使用apply方法。
Scala类中可以传参,传参一定要指定类型,有了参数就有了默认了构造。类中的属性默认有getter和setter方法
类中重载构造时,构造中第一行必须先调用默认的构造 。def this(....){....}
在同一个scala文件中,class名称和Object名称一样时,这个类叫做个对象的伴生类,这个对象叫做这个类的伴生对象,他们之间可以互相访问私有变量。
object Demo10 extends App {
  val user1 = new User("zhangsan", 15, "man")
  val user = new User( age=15, sex="man")
  /*set*/
  user.name = "lisi"
  //报错  user.age=12
  //报错  user.sex="女"
  /*get*/
  println(user.name)
  println(user.age)
  //报错  println(user.sex)
}
class User(var name: String = "aa", val age: Int, sex: String) {
  /**
    * 构造函数及get set方法都自动生成了
    * var 变量      会在有参数的构造器中,get set方法都有
    * val 常量      会在有参数的构造器中,只有get方法
    * 无变量修饰符   会在有参数的构造器中,无get set方法
    * 可以传递默认值,由指定参数创建
    * 参数都是私有的属性
    * 类自身就是public的,而且不限个数
    **/
  //主构造器,这里面写的代码,都会在对象创建的时候进行
  println("我生成了")
}
object Demo11 extends App {
  val user = new User(15)
  println(user.name)
  println(user.age)
}
class User(var name: String = "aa", val age: Int, sex: String) {
  //辅助构造器,可以定义很多,类似于java的重载
  def this(username: String) = {
    //辅助构造器参数只能在当前辅助构造函数内当做普通的常量使用
    //第一个辅助构造的首行必须是调用主构造
    this(username, 10, "男")
  }
  def this(age: Int) {
    //可以调用前面的辅助构造器
    //this(name, age, "男")
    this("lisi")
  }
}
object Demo12 extends App {
  val zhangsan = new Son("zhangsan", 12)
  println(zhangsan.name)
  println(zhangsan.add(1, 2))
}
class Father(val name: String, val age: Int) {
  def add(a: Int, b: Int): Int = {
    a + b
  }
}
/**
  * 属性复写:
  * 如果子类属性名和父类属性名一样,主类属性被隐藏
  * 可以选择override复写主类属性
  * 被复写的属性只能是val的
  * 未指定val,var的属性,本身就是私有的,和继承无关
  * 方法复写:
  * 使用override关键字
  **/
class Son(override val name: String, override val age: Int) extends Father(name, age) {
  override def add(a: Int, b: Int): Int = {
    a + b + 1
  }
}
object Demo13 extends App {
  val son = new Son()
  println(son.a)
  println(son.add(1, 2))
  //多态,强转
  val father: Father = new Son
  if (father.isInstanceOf[Son]) {
    val s: Son = father.asInstanceOf[Son]
    println(s.a)
  }
  //匿名内部类
  println(new Father {
    override var a: Int = 1
    override def add(a: Int, b: Int): Int = {
      1
    }
  }.a)
}
/**
  * 抽象类:
  * 使用abstract关键字
  **/
abstract class Father() {
  //抽象字段
  var a: Int
  //抽象方法
  def add(a: Int, b: Int): Int
}
class Son extends Father {
  override var a: Int = _
  override def add(a: Int, b: Int): Int = {
    a + b
  }
}
object Demo14 extends App {
  //使用new关键字,直接走类的构造器
  val zhangsan = new Father("zhangsan", 12)
    
  //不适用new关键字,走伴生对象的apply()方法
  val lisi = Father("lisi", 20) //进入apply()方法
    
  println(zhangsan) //name:zhangsan,age:12
  println(lisi) //name:lisi,age:20
}
//Father对象的伴生类
class Father(val name: String, val age: Int) {
  override def toString: String = s"name:${name},age:${age}"
}
//Father类的伴生对象
object Father {
  //伴生对象中使用apply()方法,创建该对象的时候会调用该方法
  def apply(name: String, age: Int): Father = {
    println("进入apply()方法")
    new Father(name, age)
  }
}
Scala中的trait非常类似于Java中的interface,主要为了解决单继承的问题。
一个类实现多个trait时,第一个关键字使用 extends,之后使用with
object Demo15 extends App {
  val son = new Son
  son.walk()	//走路
  son.eat()		//吃饭
}
trait Features {
  def walk()
}
trait Hobby {
  def eat()
}
class Son extends Features with Hobby {
  override def walk(): Unit = {
    println("走路")
  }
  override def eat(): Unit = {
    println("吃饭")
  }
}
隐式转换是在Scala编译器进行类型匹配时,如果找不到合适的类型,那么隐式转换会让编译器在作用范围内自动推导出来合适的类型,简单的说就是:把任何东西,转换成我们需要的格式。
名字无所谓,作用域范围有效,在使用到相关功能的时候,找到是否有相关的隐式函数,有就直接使用。
注意:隐式转换函数只与函数的参数类型和返回类型有关,与函数名称无关,所以作用域内不能有相同的参数类型和返回类型的不同名称隐式转换函数。
object Demo16 extends App {
  implicit def double2Double(num: Double): Int = num.toInt
  var a: Int = 10.1
  println(a) //10
  implicit def father2Son(father: Father): Son = father.toSon
  var son: Son = new Father
  son.speakDad  //Dad
}
class Father {
  def toSon: Son = {
    new Son
  }
}
class Son {
  def speakDad {
    println("Dad")
  }
}
隐式值是指在定义参数时前面加上implicit。隐式参数是指在定义方法时,方法中的部分参数是由implicit修饰【必须使用柯里化的方式,将隐式参数写在后面的括号中】。隐式转换作用就是:当调用方法时,不必手动传入方法中的隐式参数,Scala会自动在作用域范围内寻找隐式值自动传入。
隐式值和隐式参数注意:
隐式值和隐式参数一起使用
同类型的参数的隐式值只能在作用域内出现一次,同一个作用域内不能定义多个类型一样的隐式值。
implicit 关键字必须放在隐式参数定义的开头
一个方法只有一个参数是隐式转换参数时,那么可以直接定义implicit关键字修饰的参数,调用时直接创建类型不传入参数即可。
一个方法如果有多个参数,要实现部分参数的隐式转换,必须使用柯里化这种方式,隐式关键字出现在后面,只能出现一次
object Demo17 extends App {
  implicit val zs: String = "zhangsan"
  implicit val sr: Int = 100
  def printStudent(age: Int)(implicit name: String, score: Int) = {
    println(s"student :$name ,age = $age ,score = $score")
  }
  def printTeacher(implicit name: String) = {
    println(s"teacher name is = $name")
  }
  printStudent(18)     //student :zhangsan ,age = 18 ,score = 100
  printTeacher  	 //teacher name is = zhangsan
  printTeacher("lisi")  //teacher name is = lisi
}
使用implicit关键字修饰的类就是隐式类。若一个变量A没有某些方法或者某些变量时,而这个变量A可以调用某些方法或者某些变量时,可以定义一个隐式类,隐式类中定义这些方法或者变量,隐式类中传入A即可。
隐式类注意:
- 隐式类必须定义在类,包对象,伴生对象中。(必须是内部的)
- 隐式类的构造必须只有一个参数,同一个类,包对象,伴生对象中不能出现同类型构造的隐式类。
object Demo18 extends App {
  implicit class Father(son: Son) {
    def speak() = {
      println(son.name + " You Are Excellent...")
    }
  }
  val f: Father = new Son("lisi")
  f.speak() //lisi You Are Excellent...
}
class Son(val s: String) {
  var name = s
}
Scala中支持不可变集合和可变集合,不可变集合可以安全的并发访问
可变集合:scala.collection.mutable 更改原集合
不可变集合:scala.collection.immutable 不会更改原集合,只会返回一个新集合
Scala默认采用不可变集合
| 方法 | 描述 | 
|---|---|
| def apply( x: T, xs: T* ): Array[T] | 创建指定对象 T 的数组, T 的值可以是 Unit, Double, Float, Long, Int, Char, Short, Byte, Boolean。 | 
| def concat[T]( xss: Array[T]* ): Array[T] | 合并数组 | 
| def copy( src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int ): Unit | 复制一个数组到另一个数组上。相等于 Java‘s System.arraycopy(src, srcPos, dest, destPos, length)。 | 
| def empty[T]: Array[T] | 返回长度为 0 的数组 | 
| def iterate[T]( start: T, len: Int )( f: (T) => T ): Array[T] | 返回指定长度数组,每个数组元素为指定函数的返回值。 | 
| def fill[T]( n: Int )(elem: => T): Array[T] | 返回数组,长度为第一个参数指定,同时每个元素使用第二个参数进行填充。 | 
| def fill[T]( n1: Int, n2: Int )( elem: => T ): Array[Array[T]] | 返回二数组,长度为第一个参数指定,同时每个元素使用第二个参数进行填充。 | 
| def ofDim[T]( n1: Int ): Array[T] | 创建指定长度的数组 | 
| def ofDim[T]( n1: Int, n2: Int ): Array[Array[T]] | 创建二维数组 | 
| def ofDim[T]( n1: Int, n2: Int, n3: Int ): Array[Array[Array[T]]] | 创建三维数组 | 
| def range( start: Int, end: Int, step: Int ): Array[Int] | 创建指定区间内的数组,step 为每个元素间的步长 | 
| def range( start: Int, end: Int ): Array[Int] | 创建指定区间内的数组 | 
| def tabulate[T]( n: Int )(f: (Int)=> T): Array[T] | 返回指定长度数组,每个数组元素为指定函数的返回值,默认从 0 开始。 | 
| def tabulate[T]( n1: Int, n2: Int )( f: (Int, Int ) => T): Array[Array[T]] | 返回指定长度的二维数组,每个数组元素为指定函数的返回值,默认从 0 开始。 | 
object Demo19 extends App {
  //第一种方式
  val arr: Array[Int] = Array(10, 20, 30, 40)
  println(arr(0)) //10
  println(arr.mkString(",")) //10,20,30,40
  //10	20	30	40
  for (i <- arr) {
    print(i + "\t")
  }
  println()
  //10	20	30	40
  arr.foreach(x => print(x + "\t"))
  println()
  //第二种方式
  val arr2: Array[Int] = new Array(3)
  for (i <- 1.to(arr2.length)) {
    arr2(i-1) = i * i
  }
  println(arr2.mkString(",")) //1,4,9
}
import scala.collection.mutable.ArrayBuffer
object Demo20 extends App {
  val arr = ArrayBuffer[String]("a", "b", "c")
  arr.append("hello", "scala") //在元素末尾追加多个元素
  arr.+=("end1", "end2") //在元素末尾追加多个元素
  arr.+=:("start") //在开头添加元素
  println(arr.mkString(",")) //start,a,b,c,hello,scala,end1,end2
}
另外还有++=(合并),--=(差集)
| 方法 | 描述 | 
|---|---|
| def +(elem: A): List[A] | 前置一个元素列表 | 
| def ::(x: A): List[A] | 在这个列表的开头添加的元素。 | 
| def :::(prefix: List[A]): List[A] | 增加了一个给定列表中该列表前面的元素。 | 
| def ::(x: A): List[A] | 增加了一个元素x在列表的开头 | 
| def addString(b: StringBuilder): StringBuilder | 追加列表的一个字符串生成器的所有元素。 | 
| def addString(b: StringBuilder, sep: String): StringBuilder | 追加列表的使用分隔字符串一个字符串生成器的所有元素。 | 
| def apply(n: Int): A | 选择通过其在列表中索引的元素 | 
| def contains(elem: Any): Boolean | 测试该列表中是否包含一个给定值作为元素。 | 
| def copyToArray(xs: Array[A], start: Int, len: Int): Unit | 列表的副本元件阵列。填充给定的数组xs与此列表中最多len个元素,在位置开始。 | 
| def distinct: List[A] | 建立从列表中没有任何重复的元素的新列表。 | 
| def drop(n: Int): List[A] | 返回除了第n个的所有元素。 | 
| def dropRight(n: Int): List[A] | 返回除了最后的n个的元素 | 
| def dropWhile(p: (A) => Boolean): List[A] | 丢弃满足谓词的元素最长前缀。 | 
| def endsWith[B](that: Seq[B]): Boolean | 测试列表是否使用给定序列结束。 | 
| def equals(that: Any): Boolean | equals方法的任意序列。比较该序列到某些其他对象。 | 
| def exists(p: (A) => Boolean): Boolean | 测试谓词是否持有一些列表的元素。 | 
| def filter(p: (A) => Boolean): List[A] | 返回列表满足谓词的所有元素。 | 
| def forall(p: (A) => Boolean): Boolean | 测试谓词是否持有该列表中的所有元素。 | 
| def foreach(f: (A) => Unit): Unit | 应用一个函数f以列表的所有元素。 | 
| def head: A | 选择列表的第一个元素 | 
| def indexOf(elem: A, from: Int): Int | 经过或在某些起始索引查找列表中的一些值第一次出现的索引。 | 
| def init: List[A] | 返回除了最后的所有元素 | 
| def intersect(that: Seq[A]): List[A] | 计算列表和另一序列之间的多重集交集。 | 
| def isEmpty: Boolean | 测试列表是否为空 | 
| def iterator: Iterator[A] | 创建一个新的迭代器中包含的可迭代对象中的所有元素 | 
| def last: A | 返回最后一个元素 | 
| def lastIndexOf(elem: A, end: Int): Int | 之前或在一个给定的最终指数查找的列表中的一些值最后一次出现的索引 | 
| def length: Int | 返回列表的长度 | 
| def map[B](f: (A) => B): List[B] | 通过应用函数以g这个列表中的所有元素构建一个新的集合 | 
| def max: A | 查找最大的元素 | 
| def min: A | 查找最小元素 | 
| def mkString: String | 显示列表的字符串中的所有元素 | 
| def mkString(sep: String): String | 显示的列表中的字符串中使用分隔串的所有元素 | 
| def reverse: List[A] | 返回新列表,在相反的顺序元素 | 
| def sorted[B >: A]: List[A] | 根据排序对列表进行排序 | 
| def startsWith[B](that: Seq[B], offset: Int): Boolean | 测试该列表中是否包含给定的索引处的给定的序列 | 
| def sum: A | 概括这个集合的元素 | 
| def tail: List[A] | 返回除了第一的所有元素 | 
| def take(n: Int): List[A] | 返回前n个元素 | 
| def takeRight(n: Int): List[A] | 返回最后n个元素 | 
| def toArray: Array[A] | 列表以一个数组变换 | 
| def toBuffer[B >: A]: Buffer[B] | 列表以一个可变缓冲器转换 | 
| def toMap[T, U]: Map[T, U] | 此列表的映射转换 | 
| def toSeq: Seq[A] | 列表的序列转换 | 
| def toSet[B >: A]: Set[B] | 列表到集合变换 | 
| def toString(): String | 列表转换为字符串 | 
object Demo21 extends App {
  val list = List(1, 2, 3, 4, 5)
  println(list(0))  //1
  //filter过滤
  val list1 = list.filter { x => x >= 3 }
  println(list1.mkString(","))  //3,4,5
  //count统计个数
  val value = list.count(x => x > 3)
  println("count统计结果:" + value) //count统计结果:2
}
import scala.collection.mutable.ListBuffer
object Demo22 extends App {
  val listBuffer: ListBuffer[Int] = ListBuffer[Int](1,2,3,4,5)
  listBuffer.append(6,7,8,9)//末尾追加元素
  listBuffer.+=(10)//末尾追加元素
  listBuffer.+=:(100)//在开头加入元素
  listBuffer.foreach(x => print(x.toString + "\t"))
}
| 方法 | 描述 | 
|---|---|
| def +(elem: A): Set[A] | 为集合添加新元素,x并创建一个新的集合,除非元素已存在 | 
| def -(elem: A): Set[A] | 移除集合中的元素,并创建一个新的集合 | 
| def contains(elem: A): Boolean | 如果元素在集合中存在,返回 true,否则返回 false。 | 
| def &(that: Set[A]): Set[A] | 返回两个集合的交集 | 
| def &~(that: Set[A]): Set[A] | 返回两个集合的差集 | 
| def +(elem1: A, elem2: A, elems: A*): Set[A] | 通过添加传入指定集合的元素创建一个新的不可变集合 | 
| def ++(elems: A): Set[A] | 合并两个集合 | 
| def -(elem1: A, elem2: A, elems: A*): Set[A] | 通过移除传入指定集合的元素创建一个新的不可变集合 | 
| def addString(b: StringBuilder): StringBuilder | 将不可变集合的所有元素添加到字符串缓冲区 | 
| def addString(b: StringBuilder, sep: String): StringBuilder | 将不可变集合的所有元素添加到字符串缓冲区,并使用指定的分隔符 | 
| def apply(elem: A) | 检测集合中是否包含指定元素 | 
| def count(p: (A) => Boolean): Int | 计算满足指定条件的集合元素个数 | 
| def copyToArray(xs: Array[A], start: Int, len: Int): Unit | 复制不可变集合元素到数组 | 
| def diff(that: Set[A]): Set[A] | 比较两个集合的差集 | 
| def drop(n: Int): Set[A]] | 返回丢弃前n个元素新集合 | 
| def dropRight(n: Int): Set[A] | 返回丢弃最后n个元素新集合 | 
| def dropWhile(p: (A) => Boolean): Set[A] | 从左向右丢弃元素,直到条件p不成立 | 
| def equals(that: Any): Boolean | equals 方法可用于任意序列。用于比较系列是否相等。 | 
| def exists(p: (A) => Boolean): Boolean | 判断不可变集合中指定条件的元素是否存在。 | 
| def filter(p: (A) => Boolean): Set[A] | 输出符合指定条件的所有不可变集合元素。 | 
| def find(p: (A) => Boolean): Option[A] | 查找不可变集合中满足指定条件的第一个元素 | 
| def forall(p: (A) => Boolean): Boolean | 查找不可变集合中满足指定条件的所有元素 | 
| def foreach(f: (A) => Unit): Unit | 将函数应用到不可变集合的所有元素 | 
| def head: A | 获取不可变集合的第一个元素 | 
| def init: Set[A] | 返回所有元素,除了最后一个 | 
| def intersect(that: Set[A]): Set[A] | 计算两个集合的交集 | 
| def isEmpty: Boolean | 判断集合是否为空 | 
| def iterator: Iterator[A] | 创建一个新的迭代器来迭代元素 | 
| def last: A | 返回最后一个元素 | 
| def map[B](f: (A) => B): immutable.Set[B] | 通过给定的方法将所有元素重新计算 | 
| def max: A | 查找最大元素 | 
| def min: A | 查找最小元素 | 
| def mkString: String | 集合所有元素作为字符串显示 | 
| def mkString(sep: String): String | 使用分隔符将集合所有元素作为字符串显示 | 
| def product: A | 返回不可变集合中数字元素的积。 | 
| def size: Int | 返回不可变集合元素的数量 | 
| def splitAt(n: Int): (Set[A], Set[A]) | 把不可变集合拆分为两个容器,第一个由前 n 个元素组成,第二个由剩下的元素组成 | 
| def subsetOf(that: Set[A]): Boolean | 如果集合A中含有子集B返回 true,否则返回false | 
| def sum: A | 返回不可变集合中所有数字元素之和 | 
| def tail: Set[A] | 返回一个不可变集合中除了第一元素之外的其他元素 | 
| def take(n: Int): Set[A] | 返回前 n 个元素 | 
| def takeRight(n: Int):Set[A] | 返回后 n 个元素 | 
| def toArray: Array[A] | 将集合转换为数组 | 
| def toBuffer[B >: A]: Buffer[B] | 返回缓冲区,包含了不可变集合的所有元素 | 
| def toList: List[A] | 返回 List,包含了不可变集合的所有元素 | 
| def toMap[T, U]: Map[T, U] | 返回 Map,包含了不可变集合的所有元素 | 
| def toSeq: Seq[A] | 返回 Seq,包含了不可变集合的所有元素 | 
| def toString(): String | 返回一个字符串,以对象来表示 | 
object Demo23 extends App {
  val set1 = Set(1, 2, 3, 4, 4)
  set1.foreach(x => print(x + "\t"))//1	2	3	4
  println()
  //1	2	3	4
  for (s <- set1) {
    print(s + "\t")
  }
}
import scala.collection.mutable.Set
object Demo24 extends App {
  val set1 = Set[Int](1,2,3,4,5)
  set1.add(100)
  set1.+=(1,210,300)
  set1.foreach(x=>print(x+"\t"))//1	300	100	5	2	3	210	4
}
| 方法 | 描述 | 
|---|---|
| def ++(xs: Map[(A, B)]): Map[A, B] | 返回一个新的 Map,新的 Map xs 组成 | 
| def -(elem1: A, elem2: A, elems: A*): Map[A, B] | 返回一个新的 Map, 移除 key 为 elem1, elem2 或其他 elems。 | 
| def --(xs: GTO[A]): Map[A, B] | 返回一个新的 Map, 移除 xs 对象中对应的 key | 
| def get(key: A): Option[B] | 返回指定 key 的值 | 
| def iterator: Iterator[(A, B)] | 创建新的迭代器,并输出 key/value 对 | 
| def addString(b: StringBuilder): StringBuilder | 将 Map 中的所有元素附加到StringBuilder,可加入分隔符 | 
| def addString(b: StringBuilder, sep: String): StringBuilder | 将 Map 中的所有元素附加到StringBuilder,可加入分隔符 | 
| def apply(key: A): B | 返回指定键的值,如果不存在返回 Map 的默认方法 | 
| def clone(): Map[A, B] | 从一个 Map 复制到另一个 Map | 
| def contains(key: A): Boolean | 如果 Map 中存在指定 key,返回 true,否则返回 false。 | 
| def copyToArray(xs: Array[(A, B)]): Unit | 复制集合到数组 | 
| def count(p: ((A, B)) => Boolean): Int | 计算满足指定条件的集合元素数量 | 
| def default(key: A): B | 定义 Map 的默认值,在 key 不存在时返回。 | 
| def drop(n: Int): Map[A, B] | 返回丢弃前n个元素新集合 | 
| def dropRight(n: Int): Map[A, B] | 返回丢弃最后n个元素新集合 | 
| def dropWhile(p: ((A, B)) => Boolean): Map[A, B] | 从左向右丢弃元素,直到条件p不成立 | 
| def empty: Map[A, B] | 返回相同类型的空 Map | 
| def equals(that: Any): Boolean | 如果两个 Map 相等(key/value 均相等),返回true,否则返回false | 
| def exists(p: ((A, B)) => Boolean): Boolean | 判断集合中指定条件的元素是否存在 | 
| def filter(p: ((A, B))=> Boolean): Map[A, B] | 返回满足指定条件的所有集合 | 
| def filterKeys(p: (A) => Boolean): Map[A, B] | 返回符合指定条件的的不可变 Map | 
| def find(p: ((A, B)) => Boolean): Option[(A, B)] | 查找集合中满足指定条件的第一个元素 | 
| def foreach(f: ((A, B)) => Unit): Unit | 将函数应用到集合的所有元素 | 
| def init: Map[A, B] | 返回所有元素,除了最后一个 | 
| def isEmpty: Boolean | 检测 Map 是否为空 | 
| def keys: Iterable[A] | 返回所有的key/p> | 
| def last: (A, B) | 返回最后一个元素 | 
| def max: (A, B) | 查找最大元素 | 
| def min: (A, B) | 查找最小元素 | 
| def mkString: String | 集合所有元素作为字符串显示 | 
| def product: (A, B) | 返回集合中数字元素的积。 | 
| def remove(key: A): Option[B] | 移除指定 key | 
| def retain(p: (A, B) => Boolean): Map.this.type | 如果符合满足条件的返回 true | 
| def size: Int | 返回 Map 元素的个数 | 
| def sum: (A, B) | 返回集合中所有数字元素之和 | 
| def tail: Map[A, B] | 返回一个集合中除了第一元素之外的其他元素 | 
| def take(n: Int): Map[A, B] | 返回前 n 个元素 | 
| def takeRight(n: Int): Map[A, B] | 返回后 n 个元素 | 
| def takeWhile(p: ((A, B)) => Boolean): Map[A, B] | 返回满足指定条件的元素 | 
| def toArray: Array[(A, B)] | 集合转数组 | 
| def toBuffer[B >: A]: Buffer[B] | 返回缓冲区,包含了 Map 的所有元素 | 
| def toList: List[A] | 返回 List,包含了 Map 的所有元素 | 
| def toSeq: Seq[A] | 返回 Seq,包含了 Map 的所有元素 | 
| def toSet: Set[A] | 返回 Set,包含了 Map 的所有元素 | 
| def toString(): String | 返回字符串对象 | 
object Demo25 extends App {
  val map = Map[String, Int]("a" -> 100, "b" -> 200, ("c", 300), ("c", 400))
  val option1: Option[Int] = map.get("a")
  val option2: Option[Int] = map.get("aa")
  println("从map中取键为a的值\t"+option1)  //从map中取键为a的值	Some(100)
  println("从map中取键为a的值\t"+option1.get)  //从map中取键为a的值	100
  println("从map中取键为aa的值\t"+option2) //从map中取键为aa的值	None
  println("从map中取键为aa的值\t"+option2.getOrElse("no value")) //从map中取键为aa的值	no value
  println(map)  //Map(a -> 100, b -> 200, c -> 400)
  //(a,100)	(b,200)	(c,400)
  for (elem <- map) {
    print(elem + "\t")
  }
  println()
  val keys: Iterable[String] = map.keys
  //key = a ,value = 100	key = b ,value = 200	key = c ,value = 400
  keys.foreach(key => {
    val value = map.get(key).get
    print(s"key = $key ,value = $value\t")
  })
  println()
  val values: Iterable[Int] = map.values
  values.foreach(x => print(x + "\t"))  //100	200	400
  println()
}
import scala.collection.mutable.Map
object Demo26 extends App {
  val map2 = Map[String, Int]()
  map2.put("hello", 100)
  map2.put("world", 200)
  map2.put("hadoop", 200)
  println(map2.mkString("\t")) //hadoop -> 200	world -> 200	hello -> 100
  //count
  val countResult = map2.count(x => {
    x._1.equals("hadoop") && x._2 == 200
  })
  println(s"键为hadoop值为200的元素有 $countResult 个") //键为hadoop值为200的元素有 1 个
  //filter
  map2.filter(_._1 == "world").foreach(x => println((x._1, x._2))) //(world,200)
  //contains
  println("是否有键为hello的元素", map2.contains("hello"))  //(是否有键为hello的元素,true)
  //exist
  println("符合条件的元素存在么", map2.exists(x => {
    x._1.equals("hadoop")
  })) //(符合条件的元素存在么,true)
}
object Demo27 extends App {
  val tuple1: Tuple1[String] = new Tuple1("hello")
  val tuple2: (String, Int) = new Tuple2("a", 100)
  val tuple3: (Int, Boolean, Char) = new Tuple3(1, true, ‘C‘)
  val tuple4: (Int, Double, String, Boolean) = Tuple4(1, 3.4, "abc", false)
  val tuple6: (Int, Int, Int, Int, Int, String) = (1, 2, 3, 4, 5, "abc")
  val tuple22 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, "abc", 14, 15, 16, 17, 18, 19, 20, 21, 22)
  println("取值:" + tuple22._13) //取值:abc
  println("输出整个元组:" + tuple4)  //输出整个元组:(1,3.4,abc,false)
  val iter: Iterator[Any] = tuple6.productIterator
  //1	2	3	4	5	abc
  while (iter.hasNext) {
    print(iter.next() + "\t")
  }
  println()
  
  //1	2	3	4	5	abc
  tuple6.productIterator.foreach(x => print(x + "\t"))
}
能够接收函数作为参数的函数,或者返回值是函数的函数,就是高阶函数
object Demo28 extends App {
  def sumNum(num1: Int, num2: Int)(f: (Int, Int) => Int): Unit = {
    println(f(num1, num2))
  }
  sumNum(1, 2)(_ + _) 	//3
}
在Scala中_充当占位符
object Demo29 extends App {
  def add(num1: Int, num2: Int): Int = {
    num1 + num2
  }
   val intAdd: Int => Int = add(1,_)
  println(intAdd(1))  //2
  println(intAdd(2))  //3
  println(intAdd(3))  //4
}
从单个参数列表,换成多个参数列表,简化了函数的调用,主要配合隐式值使用。
object Demo30 extends App {
  def add(x: Int)(y: Int) = x + y
  println(add(1)(2)) //3
  implicit val a: Int = 10
  def implicitAdd(x: Int)(implicit y: Int) = x + y
  println(implicitAdd(1)) //11
}
主要用来转化结构
object Demo31 extends App {
  //val seq: IndexedSeq[String] = 1.to(10).map(x => x + "->")
  val seq: IndexedSeq[String] = 1.to(10).map(_ + "->")
  println(seq)  //Vector(1->, 2->, 3->, 4->, 5->, 6->, 7->, 8->, 9->, 10->)
}
object Demo32 extends App {
  val list = List(10, 20, 30, 40)
  val filterList: List[Int] = list.filter(_ > 10)
  println(filterList.mkString(",")) //20,30,40
}
object Demo33 extends App {
  val list: List[List[Int]] = List(List(1, 2), List(3, 4), List(5, 6))
  val fList: List[Int] = list.flatMap(list => list.map(_ * 2))
  println(fList) //List(2, 4, 6, 8, 10, 12)
}
object Demo34 extends App {
  val list = List(1, 2, 3, 4)
  val result: Int = list.reduce(_ + _)
  println(result) //10
}
Reduce加强版,如下wordCount案例
import scala.collection.mutable.Map
object Demo35 extends App {
  val list = List("a", "b", "c", "d", "a", "b", "c", "a", "b", "a")
  //写法一
  val metaMap1: Map[String, Int] = Map[String, Int]()
  val foldMap1: Map[String, Int] = list.foldLeft(metaMap1)((mp, listElement) => {
    mp(listElement) = mp.getOrElse(listElement, 0) + 1
    mp
  })
  println(foldMap1)  //Map(b -> 3, d -> 1, a -> 4, c -> 2)
  //写法二
  val metaMap2: Map[String, Int] = Map[String, Int]()
  val foldMap2: Map[String, Int] = (metaMap2 /: list) ((mp, listElement) => {
    mp(listElement) = mp.getOrElse(listElement, 0) + 1
    mp
  })
  println(foldMap2) //Map(b -> 3, d -> 1, a -> 4, c -> 2)
}
保存折叠过程中的结果
object Demo36 extends App {
  val list: List[Int] = 1.to(10).toList
  val result: List[Int] = list.scan(0)(_ + _)
  println(result) //List(0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55)
}
object Demo37 extends App {
  val list1: List[Int] = 1.to(10).toList
  val list2: List[Int] = 11.to(19).toList
  val tuples1: List[(Int, Int)] = list1.zip(list2)
  val tuples2: List[(Int, Int)] = list1.zipAll(list2, 100, 200)
  //如果数量不等,多的丢弃
  println(tuples1) //List((1,11), (2,12), (3,13), (4,14), (5,15), (6,16), (7,17), (8,18), (9,19))
  //如果数量不等,使用默认值补齐
  println(tuples2) //List((1,11), (2,12), (3,13), (4,14), (5,15), (6,16), (7,17), (8,18), (9,19), (10,200))
  val unzip: (List[Int], List[Int]) = tuples1.unzip
  println(unzip) //(List(1, 2, 3, 4, 5, 6, 7, 8, 9),List(11, 12, 13, 14, 15, 16, 17, 18, 19))
}
spark中数量不等,会抛异常
object Demo38 extends App {
  val list = List("a", "b", "c", "d", "a", "b", "c", "a", "b", "a")
    
  val map: Map[String, List[String]] = list.groupBy(ele => ele)
  println(map) //Map(b -> List(b, b, b), d -> List(d), a -> List(a, a, a, a), c -> List(c, c))
    
  val result: Map[String, Int] = map.map(kv => (kv._1, kv._2.length))
  println(result) //Map(b -> 3, d -> 1, a -> 4, c -> 2)
}
object Demo39 extends App {
  val list = List(1, 5, 8, 2, 3, 6)
  //sorted排序
  val slist1: List[Int] = list.sorted
  println(slist1) //List(1, 2, 3, 5, 6, 8)
  val slist2: List[Int] = list.sorted(Ordering.Int.reverse)
  println(slist2) //List(8, 6, 5, 3, 2, 1)
  val sonList = List(Son("zhangsan", 10), Son("lisi", 5), Son("wangwu", 15))
  implicit val sonOrdering = new Ordering[Son] {
    override def compare(x: Son, y: Son): Int = {
      x.age - y.age
    }
  }
  println(sonList.sorted) //List(name:lisi,age:5, name:zhangsan,age:10, name:wangwu,age:15)
  println(sonList.sorted(sonOrdering.reverse)) //List(name:wangwu,age:15, name:zhangsan,age:10, name:lisi,age:5)
  //sortWith排序
  val sortWithList: List[Int] = list.sortWith((x, y) => x < y)
  println(sortWithList) //List(1, 2, 3, 5, 6, 8)
  val sortWithSon: List[Son] = sonList.sortWith((x, y) => x.age > y.age)
  println(sortWithSon) //List(name:wangwu,age:15, name:zhangsan,age:10, name:lisi,age:5)
  //sortBy
  val sons1: List[Son] = sonList.sortBy(son=>(son.name.length))(Ordering.Int.reverse)
  println(sons1)  //List(name:zhangsan,age:10, name:wangwu,age:15, name:lisi,age:5)
  val sons2: List[Son] = sonList.sortBy(son=>(son.name,son.age))(Ordering.Tuple2(Ordering.String.reverse,Ordering.Int.reverse))
  println(sons2) //List(name:zhangsan,age:10, name:wangwu,age:15, name:lisi,age:5)
}
class Son(val name: String, val age: Int) {
  override def toString: String = s"name:${name},age:${age}"
}
object Son {
  def apply(name: String, age: Int): Son = new Son(name, age)
}
object Demo40 extends App {
  val list = List(1, 2, 3, 5, 6, 8)
  val stream: Stream[Int] = list.toStream
  println(stream.head) //1
  println(stream.tail) //Stream(2, ?)
  stream.tail.foreach(x => print(s"$x\t"))  //2	3	5	6	8
  println()
  stream.take(3).foreach(x => print(s"$x\t")) //1	2	3
}
object Demo41 extends App {
  val list = List(1, 2, 3, 5, 6, 8)
  val view = list.view
  println(view.head)  //1
  view.tail.foreach(x => print(s"$x\t"))  //2	3	5	6	8
}
object Demo42 extends App {
  val list = 1.to(10).toList
  val slice1: List[Int] = list.slice(0, list.length - 1)
  val slice2: List[Int] = list.slice(1, list.length)
  val tuples: List[(Int, Int)] = slice1.zip(slice2)
  println(tuples) //List((1,2), (2,3), (3,4), (4,5), (5,6), (6,7), (7,8), (8,9), (9,10))
  val result: List[String] = tuples.map(tuples => tuples._1 + "->" + tuples._2)
  println(result) //List(1->2, 2->3, 3->4, 4->5, 5->6, 6->7, 7->8, 8->9, 9->10)
}
object Demo43 extends App {
  def operator(x: Int, y: Int, opt: String): Any = {
    opt match {
      case "+" => x + y
      case "-" => x - y
      case "*" => x * y
      case "/" => x.toDouble / y.toDouble
      case _ => 
    }
  }
  println(operator(3, 2, "+")) //5
  println(operator(3, 2, "-")) //1
  println(operator(3, 2, "*")) //6
  println(operator(3, 2, "/")) //1.5
  println(operator(3, 2, "xxx")) //()
}
object Demo44 extends App {
  def operator(x: Char, y: Char, opt: String): Any = {
    opt match {
      case "+" => x + y
      case "-" => x - y
      case "*" => x * y
      case "/" => x.toDouble / y.toDouble
      case _ if (!Character.isDigit(x) || !Character.isDigit(y)) => "数字传递错误"    //模式匹配守卫
      case _ => "error"
    }
  }
  println(operator(‘3‘, ‘2‘, "+")) //5
  println(operator(‘3‘, ‘2‘, "-")) //1
  println(operator(‘3‘, ‘2‘, "*")) //6
  println(operator(‘3‘, ‘2‘, "/")) //1.5
  println(operator(‘3‘, ‘x‘, "xxx")) //数字传递错误
  println(operator(‘3‘, ‘2‘, "xxx")) //error
}
object Demo45 extends App {
  //z...  ch在自己的作用域中,当做变量来处理,那么就可以匹配任意值,并赋值给ch
  val ch = ‘a‘
  ‘z‘ match {
    case ‘a‘ => println("a...")
    case ch => println(ch + "...")
    case _ => println("_...")
  }
  //_...  当首字母大写时,当做常量来处理,正常匹配流程
  val Ch = ‘a‘
  ‘z‘ match {
    case ‘a‘ => println("a...")
    case Ch => println(Ch + "...")
    case _ => println("_...")
  }
}
object Demo46 extends App {
  /**
    * 20
    * a
    * 30
    * b
    * 40
    * c
    */
  val list = List(10, "a", 20, "b", 30, "c")
  for (elem <- list) {
    elem match {
      case n: Int => println(n + 10)
      case s: String => println(s)
      case _ =>
    }
  }
  //int array
  val arr: Array[_] = Array[Int]()
  arr match {
    case arr: Array[String] => println("string array")
    case arr: Array[Int] => println("int array")
  }
}
使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。
样例类默认帮你实现了apply,toString,equals,copy和hashCode等方法。
样例类可以new, 也可以不用new
和模式匹配兼容性很好
object Demo47 extends App {
  val p1 = Father("lisi", 20)
  val p2 = Son("wangwu", 30)
  /**
    * father->name:lisi,age:20
    * son->name:wangwu,age:30
    */
  val list = List(p1, p2)
  list.foreach(x => {
    x match {
      case Father(name,age) => println(s"father->name:$name,age:$age")
      case Son(name,age) => println(s"son->name:$name,age:$age")
      case _ => println("no match")
    }
  })
}
abstract class Person()
case class Father(name: String, age: Int)extends Person
case class Son(name: String, age: Int) extends Person
如果一个方法中没有match 只有case,这个函数可以定义成PartialFunction偏函数。偏函数定义时,不能使用括号传参,默认定义PartialFunction中传入一个值,匹配上了对应的case,返回一个值。
只会出现满足的case,类似filter+map效果
import scala.actors.Actor
object Demo45 extends App {
  //创建actor的消息接收和传递
  val actor = new myActor()
  //启动
  actor.start()
  //发送消息写法
  /**
    * get String =i love you !
    * get Int
    * get default
    * */
  actor ! "i love you !"
  actor ! 500
  actor ! true
}
class myActor extends Actor {
  def act() {
    while (true) {
      receive {
        case x: String => println("get String =" + x)
        case x: Int => println("get Int")
        case _ => println("get default")
      }
    }
  }
}
import scala.actors.Actor
object Demo45 extends App {
  val actor1 = new Actor1()
  actor1.start()
  val actor2 = new Actor2(actor1)
  actor2.start()
  /**
    * i sava msg! = i love you !
    * i love you too !
    * could we have a date !
    * */
}
case class Message(actor: Actor, msg: Any)
class Actor1 extends Actor {
  def act() {
    while (true) {
      receive {
        case msg: Message => {
          println("i sava msg! = " + msg.msg)
          msg.actor ! "i love you too !"
        }
        case msg: String => println(msg)
        case _ => println("default msg!")
      }
    }
  }
}
class Actor2(actor: Actor) extends Actor {
  actor ! Message(this, "i love you !")
  def act() {
    while (true) {
      receive {
        case msg: String => {
          if (msg.equals("i love you too !")) {
            println(msg)
            actor ! "could we have a date !"
          }
        }
        case _ => println("default msg!")
      }
    }
  }
}
原文:https://www.cnblogs.com/ttzzyy/p/12697855.html