Scala操作
0 Scala简介
- Scala是一门多范式的编程语言,一种类似java的编程语言 [1] ,设计初衷是实现可伸缩的语言 [2] 、并集成面向对象编程和函数式编程的各种特性。
1 Scala环境
2 数据类型
-
Scala中定义变量使用var,定义常量使用val ,变量可变,常量不可变.变量和常量类型可以省略不写,会自动推断。
- val 不可变变量声明 --> val 变更名 : 变量类型 = 值
- var 可变变量声明 --> var 变更名 : 变量类型 = 值
- 一般情况下我们可以不写类型,这样scala会自动判定类型 --> val 变量名 = 值 | var 变量名 = 值
-
Scala中每行后面都会有分号自动推断机制,不用显式写出“;”
-
建议在Scala中命名使用驼峰命名法
-
案例
object Test {
def main(args: Array[String]): Unit = {
val spark = "hello spark"
//spark = "haha" --> 错误,不能给常量再赋值
println("常量" + spark)
var helloHadoop = "hello hadoop"
helloHadoop = "HELLO HADOOP"
println("变量" + helloHadoop)
//声明一个数字
val num: Int = 55
println("声明一个数字" + num)
//声明一个字符串
val word: String = "哈哈"
println("声明一个字符串" + word)
//声明一个浮点数
val fnum: Float = 33.33333333333333f
println("声明一个浮点数" + fnum)
val dnum: Double = 33.33333333333333
println("声明一个浮点数" + dnum)
//声明一个判断类型
val flagt: Boolean = true
val flagf: Boolean = false
println("声明一个判断类型" + flagt)
println("声明一个判断类型" + flagf)
}
}
测试
3 类和对象
-
Scala object相当于java中的单例,object中定义的全是静态的,相当于java中的工具类,Object默认不可以传参,对象要传参,使用apply方法。
-
Scala类中可以传参,传参一定要指定类型,有了参数就有了默认了构造。类中的属性默认有getter和setter方法
-
类中重载构造时,构造中第一行必须先调用默认的构造 。def this(....)
-
Scala中当new class 时,类中除了方法不执行【除了构造方法】,其他都执行。
-
在同一个scala文件中,class名称和Object名称一样时,这个类叫做个对象的伴生类,这个对象叫做这个类的伴生对象,他们之间可以互相访问私有变量。
-
案例1
class Person(xname: String, xage: Int) {
println("******* Person Class Start*******")
private val name = xname
var age = xage
var gender = 'M'
//观察重载的构造器
def this(yname: String, yage: Int, ygender: Char) {
this(yname, yage)
this.gender = ygender
}
//观察object的静态性。直接调用其属性
def sayName() = {
println(name + " hello world... " + classAndObj.name)
}
println("******* Person Class End*******")
}
//观察伴生对象可以使用私有属性
object Person{
val p = new Person("zhangsan", 20)
println("伴生对象:"+p.name)
}
object classAndObj {
println("******* classAndObj Object *******")
val name = "wangwu"
//object要传参需要apply方法
def apply(i: Int) = {
println("Score is " + i)
}
def apply(i: Int, s: String) = {
println("name is " + s + ",score is " + i)
}
def main(args: Array[String]): Unit = {
//object要传参需要apply方法
classAndObj(1000)
classAndObj(1000, "zhaoliu")
val p = new Person("zhangsan", 20)
//println(p.name)不可以直接调用私有属性
p.sayName()
println(p.gender)
val p1 = new Person("lisi", 18, 'F')
p1.sayName()
println(p1.gender)
p1.age = 200
println(p1.age)
}
}
测试
- 案例2
class Person {
var name: String = _ //未赋值,会生成getter和setter方法
val age = 10 //只会生成getter方法
private[this] val gender = "male" //只能在定义里使用,实例也不能调用
}
object ObjTest {
def main(args: Array[String]): Unit = {
val p = new Person //括号可省略
p.name = "zhangsan"
println(p.name + ":" + p.age)
//println(p.gender)
}
}
测试
- 案例3
class Person(val name : String,val age :Int) {
//1.参数直接跟在类名后面的是主构造器
//2.主构造器中的参数最后会被编译成字段
//3.主构造器在执行的时候会执行类中的所有语句
//4.假设参数声明时不带val和var,那么相当于private[this]!!!
println("这是一个主构造器")
}
object ObjTest {
def main(args: Array[String]): Unit = {
val p = new Person("zhangsan",15)
println(p.name + ":" + p.age)
}
}
测试
- 案例4
class Person(val name: String, val age: Int) {
//1.参数直接跟在类名后面的是主构造器
//2.主构造器中的参数最后会被编译成字段
//3.主构造器在执行的时候会执行类中的所有语句
//4.假设参数声明时不带val和var,那么相当于private[this]!!!
println("这是一个主构造器")
var gender : String = _
//1. 附属构造器,名称是this
//2. 每一个附属构造器必须首先调用已经存在的子构造器或者附属构造器
def this(name: String, age: Int, gender: String) {
this(name,age)
this.gender = gender
}
}
object ObjTest {
def main(args: Array[String]): Unit = {
val p = new Person("zhangsan", 15,"male")
println(p.name + ":" + p.age + ":" + p.gender)
}
}
测试
- 案例5
class Person(val name: String, val age: Int) {
println("这是一个主构造器")
}
class Student(name: String, age: Int, val major: String) extends Person(name, age) {
println("这是Person子类的一个主构造器")
}
object ObjTest {
def main(args: Array[String]): Unit = {
val s = new Student("zhangsan", 15, "Math")
print(s.name + ":" + s.age + ":" + s.major)
}
}
测试
- 案例6
class Person(val name: String, val age: Int) {
println("这是一个主构造器")
val school = "haha"
def eat(): Unit ={
println("人吃饭")
}
}
class Student(name: String, age: Int, val major: String) extends Person(name, age) {
println("这是Person子类的一个主构造器")
override val school = "xixi"
override def toString = "override toString..."
override def eat(): Unit ={
println("学生吃饭")
}
}
object ObjTest {
def main(args: Array[String]): Unit = {
val s = new Student("zhangsan", 15, "Math")
println(s.name + ":" + s.age + ":" + s.major)
println(s.toString)
println(s.school)
s.eat()
}
}
测试
4 流程控制
4.1 if | else if | else -- 三元 -- for -- while -- do while
- 案例
object Test {
def main(args: Array[String]): Unit = {
//if | else if | else
val x = 3
if (x == 1) {
println("x==1")
} else if (x == 2) {
println("x==2")
} else {
println("其他情况")
}
//三元
val num = if (x > 0) 1 else 0
println(num)
println("*****")
//while
var (n, m) = (3, 0)
while (n > 0) {
m = m + n
n = n - 1
}
println(m)
println("*****")
//do while
do{
println(m)
}while(m<0)
println("*****")
//for 1-10
for (i <- 1 to 10) {
print(i+"\t")
}
println()
println("*****")
//for 1-9
for (i <- 1 until 10) {
print(i+"\t")
}
println()
println("*****")
//for 1-9 偶数
for (i <- 1 until 10 if i % 2 == 0) {
print(i+"\t")
}
println()
println("*****")
//操作符函数写法
println(1.to(10))
println(1.until(10))
println(1.until(10,2))
println("*****")
//foreach
val str = "abcd"
str.foreach(x => print(x+"\t"))
println()
str.foreach(print(_))
println()
str.foreach(print)
}
}
测试
4.2 match case
- 案例
/**
* Match 模式匹配
* 1.case _ 什么都匹配不上匹配,放在最后
* 2.match 可以匹配值还可以匹配类型
* 3.匹配过程中会有数值的转换
* 4.从上往下匹配,匹配上之后会自动终止
* 5.模式匹配外部的“{..}”可以省略
*/
object Test extends App {
def MatchTest(o: Any) =
o match {
case i: Int => println(s"type is Int ,value = $i")
case 1 => println("value is 1")
case d: Double => println(s"type is Double ,value = $d")
case q if q.equals("abc") => println("value is abc")
case s: String => println(s"type is String ,value = $s")
case 'a' => println("value is a")
case _ => {
println("no match...")
}
}
val tp = (1, 1.2, "abc", 'a', "xx", true)
val iter: Iterator[Any] = tp.productIterator
iter.foreach(MatchTest)
}
测试
4.3 偏函数
- 如果一个方法中没有match 只有case,这个函数可以定义成PartialFunction偏函数。偏函数定义时,不能使用括号传参,默认定义PartialFunction中传入一个值,匹配上了对应的case,返回一个值。
- 案例
object Test extends App {
def MyTest : PartialFunction[String,String] = {
case "scala" =>{"scala"}
case "hello"=>{"hello"}
case _=> {"no match ..."}
}
println(MyTest("scala"))
}
测试
4.4 样例类(case classes)
- 使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。
- 样例类默认帮你实现了toString,equals,copy和hashCode等方法。
- 样例类可以new, 也可以不用new
- 案例1
case class Person1(name: String, age: Int)
object Test extends App {
val p1 = new Person1("zhangsan", 10)
val p2 = Person1("lisi", 20)
val p3 = Person1("wangwu", 30)
val list = List(p1, p2, p3)
list.foreach(x => {
x match {
case Person1("zhangsan", 10) => println("zhangsan")
case Person1("lisi", 20) => println("lisi")
case _ => println("no match")
}
})
}
测试
- 案例2
class Code {
}
case class Book(name:String,author : String){
//构造器中的每一个类型为val
//不用new就可以产生对象(调用apply()方法)
}
object Test extends App {
val hadoop = Book("Hadoop","zhangsan")
hadoop match {
case Book(name,author) =>println("this is a Book")
case _ =>println("unknown")
}
}
测试
5 方法和函数
- 案例1
object Test {
//无返回值函数
def helloPrintName1(name: String): Unit = {
println("无返回值函数: " + name)
}
//无返回值函数,: Unit 可以省略
def helloPrintName2(name: String) = {
println("无返回值函数: " + name)
}
//有返回值函数
def helloName1(name: String): String = {
return "有返回值函数: " + name
}
//有返回值函数,默认最后一句就是返回值,可以省略return
def helloName2(name: String): String = {
"有返回值函数: " + name
}
//把匿名函数赋值给变量
val add = (x: Int, y: Int) => x + y
//柯里化
def add2(x: Int)(y: Int) = x + y
//可变参数
def helloName3(name: String*) = {
name.foreach(x => print("可变参数: " + x + "\t"))
}
//默认参数值
def helloPrintName4(name: String = "china") = {
println("默认参数值: " + name)
}
def main(args: Array[String]): Unit = {
helloPrintName1("scala")
helloPrintName2("scala")
println(helloName1("scala"))
println(helloName2("scala"))
println("把匿名函数赋值给变量", add(1, 2))
println("柯里化", add2(1)(2))
helloName3("zhangsan", "lisi", "wangwu")
println()
helloPrintName4()
helloPrintName4("Korean")
}
}
测试
- 案例2
import java.util.Date
object Test {
//递归方法5的阶乘
def recursive(num: Int): Int = {
if (num == 1)
num
else
num * recursive(num - 1)
}
//偏应用函数
def log(author: String, date: Date, msg: String) = {
println(s"$author:date is " + date + ",log is " + msg)
}
val date = new Date()
val author = "Heaton"
//想要调用log,以上变化的是第三个参数,可以用偏应用函数处理
val logWithDate = log(author, date, _: String)
def main(args: Array[String]): Unit = {
println("递归方法5的阶乘", recursive(5))
log(author,date, "log1")
log(author,date, "log2")
logWithDate("log33")
logWithDate("log44")
}
}
测试
- 案例3高阶函数及柯里化
object Test extends App {
//函数的参数是函数
def sum(v1: Int, v2: Int): Int = {
v1 + v2
}
def hightSum(f: (Int, Int) => Int, a: Int, b: Int): Int = {
f(a, b)
}
println("函数的参数是函数", hightSum(sum, 1, 2))
println("函数的参数是函数->使用匿名函数", hightSum((x: Int, y: Int) => x + y, 2, 2))
//函数的返回是函数(柯里化就是简写)
//1,2,3,4相加
def hightSum2(a: Int, b: Int): (Int, Int) => Int = {
def f2(v1: Int, v2: Int): Int = {
v1 + v2 + a + b
}
f2
}
println("函数的返回是函数" + hightSum2(1, 2)(3, 4))
//函数的参数是函数,函数的返回是函数
def hightFun(f: (Int, Int) => Int): (Int, Int) => Int = {
f
}
println("函数的参数是函数" + hightFun(sum)(100, 200))
println("函数的参数是函数->匿名函数" + hightFun((a, b) => a + b)(200, 200))
//如果函数的参数在方法体中只使用了一次 那么可以写成_表示
println("函数的参数是函数->简写" + hightFun(_ + _)(200, 200))
//柯里化函数
def currie(a: Int, b: Int)(c: Int, d: Int) = {
a + b + c + d
}
println("柯里化函数" + currie(1, 2)(3, 4))
}
测试
6 集合
6.1 数组
- 案例
import scala.collection.mutable.ArrayBuffer
object Test extends App {
/**
* 创建定长数组两种方式:
* 1.new Array[String](3)
* 2.直接Array
*/
//创建类型为Int 长度为3的数组
val arr1 = new Array[String](3)
//创建String 类型的数组,直接赋值
val arr2 = Array[String]("1", "2", "3")
//赋值
arr1(0) = "100"
arr1(1) = "200"
arr1(2) = "300"
/**
* 遍历两种方式
*/
print("for循环遍历" + "\t")
for (i <- arr1) {
print(i + "\t")
}
println()
print("foreach遍历" + "\t")
arr1.foreach(x => print(x + "\t"))
println()
print("foreach遍历" + "\t")
arr1.foreach(print)
println()
/**
* 数组的一些常用方法
*/
//拼接方法
var arr3 = Array.concat(arr1, arr2)
print("拼接方法结果:" + "\t")
arr3.foreach((x) => print(x + "\t"))
println()
//初始赋值方法
print("初始赋值结果:" + "\t")
var arr4 = Array.fill(3)("hello")
arr4.foreach((x) => print(x + "\t"))
println()
/**
* 创建二维数组和遍历
*/
val arr5 = new Array[Array[String]](2)
arr5(0) = Array("1", "2", "3")
arr5(1) = Array("4", "5", "6")
println("二维数组遍历结果:")
for (i <- 0 until arr5.length) {
for (j <- 0 until arr5(i).length) {
print(arr5(i)(j) + " ")
}
}
println()
println("二维数组遍历结果:")
for (i <- 0 until arr5.length; j <- 0 until arr5(i).length) {
print(arr5(i)(j) + " ")
}
println()
println("二维数组遍历结果:")
arr5.foreach { arr => {
arr.foreach { (x) => print(x + "\t") }
}
}
println()
/**
* 可变长度数组的定义
*/
val arr = ArrayBuffer[String]("a", "b", "c")
arr.append("hello", "scala") //在元素末尾追加多个元素
arr.+=("end1", "end2") //在最后追加多个元素
arr.+=:("start") //在开头添加元素
print("可变数组遍历" + "\t")
arr.foreach((x) => print(x + "\t"))
}
测试
- 常用方法
方法 | 描述 |
---|---|
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 开始。 |
6.2 列表List
- 案例
import scala.collection.mutable.ListBuffer
object Test extends App {
//创建
val list = List(1, 2, 3, 4, 5)
//取出某一个
println("取出某一个", list(0))
//遍历
print("遍历\t")
list.foreach { x => print(x + "\t") }
println()
//filter过滤
val list1 = list.filter { x => x > 3 }
print("filter过滤结果\t")
list1.foreach { x => print(x + "\t") }
println()
//count统计个数
val value = list.count(x => x > 3)
println("count统计结果:" + value)
//map
val nameList = List("hello hadoop", "hello scala", "hello world")
val mapResult: List[Array[String]] = nameList.map(x => x.split(" "))
print("map处理结果\t")
mapResult.foreach(x => print(x.toString + "\t"))
println()
print("map处理结果\t")
mapResult.foreach(x => x.foreach(y => print(y + "\t")))
println()
//flatmap
val flatMapResult: List[String] = nameList.flatMap(x => x.split(" "))
print("flatmap处理结果\t")
flatMapResult.foreach(x => print(x.toString + "\t"))
println()
/**
* 可变长list
*/
val listBuffer: ListBuffer[Int] = ListBuffer[Int](1,2,3,4,5)
listBuffer.append(6,7,8,9)//追加元素
listBuffer.+=(10)//在后面追加元素
listBuffer.+=:(100)//在开头加入元素
print("可变长list遍历\t")
listBuffer.foreach(x => print(x.toString + "\t"))
}
测试
- 常用方法
方法 | 描述 |
---|---|
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 | 列表转换为字符串 |
6.3 集合set
- 案例1
object Test extends App {
//创建
val set1 = Set(1, 2, 3, 4, 4)
val set2 = Set(1, 2, 5)
//遍历 set会自动去重
print("遍历\t")
set1.foreach(x => print(x + "\t"))
println()
print("遍历\t")
for (s <- set1) {
print(s + "\t")
}
println()
//交集
val set3 = set1.intersect(set2)
print("交集遍历\t")
set3.foreach(x => print(x + "\t"))
println()
val set4 = set1.&(set2)
print("交集遍历\t")
set4.foreach(x => print(x + "\t"))
println()
//差集
print("差集遍历\t")
set1.diff(set2).foreach(x => print(x + "\t"))
println()
print("差集遍历\t")
set1.&~(set2).foreach(x => print(x + "\t"))
println()
//子集
println("是否是子集\t"+set1.subsetOf(set2))
//最大值
println("最大值\t"+set1.max)
//最小值
println("最小值\t"+set1.min)
//转成数组,list
print("转成数组\t")
set1.toArray.foreach(x => print(x + "\t"))
println()
print("转成列表\t")
set1.toList.foreach(x => print(x + "\t"))
println()
//mkString集合所有元素作为字符串显示
println("集合所有元素作为字符串显示"+set1.mkString)
println("集合所有元素作为字符串显示分隔符\t"+set1.mkString("\t"))
}
测试
- 案例2
import scala.collection.mutable
import scala.collection.immutable
object Test extends App {
/**
* 可变长Set->scala.collection.mutable.Set
* 不可变长Set->scala.collection.immutable.Set
*/
val set1 = mutable.Set[Int](1,2,3,4,5)
val set2 = immutable.Set[Int](1,2,3,4,5)
set1.add(100)
set1.+=(200)
set1.+=(1,210,300)
print("可变长set遍历")
set1.foreach(x=>print(x+"\t"))
//set2.add(100) 报错
}
测试
- 常用方法
方法 | 描述 |
---|---|
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 | 返回一个字符串,以对象来表示 |
6.4 map
- 案例1
object Test 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)
println("从map中取键为a的值\t"+option1.get)
println("从map中取键为aa的值\t"+option2)
println("从map中取键为aa的值\t"+option2.getOrElse("no value"))
print("遍历:")
println(map)
print("遍历:")
for (elem <- map) {
print(elem + "\t")
}
println()
print("遍历键->拿到值:")
val keys: Iterable[String] = map.keys
keys.foreach(key => {
val value = map.get(key).get
print(s"key = $key ,value = $value\t")
})
println()
print("遍历值:")
val values: Iterable[Int] = map.values
values.foreach(x => print(x + "\t"))
println()
val map1 = Map[String, Int](("a", 1), ("b", 2), ("c", 3), ("d", 4))
val map2 = Map[String, Int](("a", 100), ("b", 2), ("c", 300), ("e", 500))
val result1: Map[String, Int] = map1.++(map2)
val result2: Map[String, Int] = map1.++:(map2)
print("合并后的结果:")
result1.foreach(x => print(x + "\t"))
println()
print("合并后的结果:")
result2.foreach(x => print(x + "\t"))
println()
}
测试
- 案例2
import scala.collection.mutable
import scala.collection.immutable
object Test extends App {
//不可变长map->scala.collection.immutable.Map
//可变长map->scala.collection.mutable.Map
val map1 = immutable.Map[String, Int]("a" -> 100, "b" -> 200, ("c", 300), ("c", 400))
val map2 = mutable.Map[String, Int]()
//map1.put("hello",100)报错
map2.put("hello", 100)
map2.put("world", 200)
map2.put("hadoop", 200)
print("可变长map遍历:\t")
map2.foreach(x => print(x + "\t"))
println()
//count
val countResult = map2.count(p => {
p._1.equals("hadoop") && p._2 == 200
})
println(s"键为hadoop值为200的元素有 $countResult 个")
//filter
map2.filter(_._1.equals("world")).foreach(x => println("过滤后的元素", x._1, x._2))
//contains
println("是否有键为hello的元素", map2.contains("hello"))
//exist
println("符合条件的元素存在么",map2.exists(x => {
x._1.equals("hadoop")
}))
}
测试
- 常用方法
方法 | 描述 |
---|---|
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 | 返回字符串对象 |
6.5 元组Tuple
- val tuple = new Tuple(1) 可以使用new
- val tuple2 = Tuple(1,2) 可以不使用new,也可以直接写成val tuple3 =(1,2,3)
- 取值用”._XX” 可以获取元组中的值
- 注意:tuple最多支持22个参数
- 案例
object Test 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("针对2元组的倒转方法" + tuple2.swap)
val value: String = tuple22._13
println("取值", value)
println("输出整个元组" + tuple4)
print("遍历:\t")
val iter: Iterator[Any] = tuple6.productIterator
while (iter.hasNext) {
print(iter.next() + "\t")
}
println()
print("遍历:\t")
tuple6.productIterator.foreach(x => print(x + "\t"))
}
测试
7 抽象类
- 案例
abstract class Person {
def speak
val name: String
var age: Int
}
class Student extends Person {
val name = "zhangsan"
var age = 10
def speak = {
println("speak!!!")
}
}
object code extends App {
val s = new Student
s.speak
println(s.name + ":" + s.age)
}
测试
8 Trait特性(能够带有具体实现的接口)
- 案例1
/**
* 一个类继承多个trait时,第一个关键字使用 extends,之后使用with
* trait 不可以传参
*/
trait Read {
def read(name: String) = {
println(s"$name is reading...")
}
}
trait Listen {
def listen(name: String) = {
println(s"$name is listening...")
}
}
class Human() extends Read with Listen {
}
object Test extends App {
val h = new Human()
h.read("zhangsan")
h.listen("lisi")
}
测试
- 案例2
/**
* Trait中可以有方法体的实现或者方法体的不实现,类继承了Trait要实现Trait中没有实现的方法
*/
trait IsEquale{
def isEqu(o:Any):Boolean
def isNotEqu(o:Any) :Boolean = !isEqu(o)
}
class Point(xx:Int,xy:Int) extends IsEquale {
val x = xx
val y = xy
override def isEqu(o: Any): Boolean = {
o.isInstanceOf[Point]&&o.asInstanceOf[Point].x==this.x
}
}
object Test extends App {
val p1 = new Point(1,2)
val p2 = new Point(1,3)
println(p1.isNotEqu(p2))
}
测试
7 apply()方法 及 静态方法 及 单例
- 案例1
class ApplyTest{
def apply() = "Apply"
def test{
println("test")
}
}
object ApplyTest{
def apply() = new ApplyTest()
}
object Test extends App {
val a = ApplyTest()//类加()调用了对象的apply()方法
a.test
val t = new ApplyTest
print(t())//对象加()就是调用类的apply()方法
}
测试
- 案例2
object ApplyTest {
var count = 0
def incr: Unit = {
count = count + 1
}
}
object Test extends App {
for (i <- 1 until 10) {
ApplyTest.incr
}
print(ApplyTest.count)
}
测试
8 隐式转换
-
隐式转换是在Scala编译器进行类型匹配时,如果找不到合适的类型,那么隐式转换会让编译器在作用范围内自动推导出来合适的类型。
-
1.隐式值与隐式参数
- 隐式值是指在定义参数时前面加上implicit。隐式参数是指在定义方法时,方法中的部分参数是由implicit修饰【必须使用柯里化的方式,将隐式参数写在后面的括号中】。隐式转换作用就是:当调用方法时,不必手动传入方法中的隐式参数,Scala会自动在作用域范围内寻找隐式值自动传入。
- 隐式值和隐式参数注意:
- 1). 同类型的参数的隐式值只能在作用域内出现一次,同一个作用域内不能定义多个类型一样的隐式值。
- 2). implicit 关键字必须放在隐式参数定义的开头
- 3). 一个方法只有一个参数是隐式转换参数时,那么可以直接定义implicit关键字修饰的参数,调用时直接创建类型不传入参数即可。
- 4). 一个方法如果有多个参数,要实现部分参数的隐式转换,必须使用柯里化这种方式,隐式关键字出现在后面,只能出现一次
-
2.隐式转换函数
- 隐式转换函数是使用关键字implicit修饰的方法。当Scala运行时,假设如果A类型变量调用了method()这个方法,发现A类型的变量没有method()方法,而B类型有此method()方法,会在作用域中寻找有没有隐式转换函数将A类型转换成B类型,如果有隐式转换函数,那么A类型就可以调用method()这个方法。
- 隐式转换函数注意:隐式转换函数只与函数的参数类型和返回类型有关,与函数名称无关,所以作用域内不能有相同的参数类型和返回类型的不同名称隐式转换函数。
-
3.隐式类
- 使用implicit关键字修饰的类就是隐式类。若一个变量A没有某些方法或者某些变量时,而这个变量A可以调用某些方法或者某些变量时,可以定义一个隐式类,隐式类中定义这些方法或者变量,隐式类中传入A即可。
- 隐式类注意:
- 1).隐式类必须定义在类,包对象,伴生对象中。
- 2).隐式类的构造必须只有一个参数,同一个类,包对象,伴生对象中不能出现同类型构造的隐式类。
-
案例1
object Test extends App {
def Student(age: Int)(implicit name: String, i: Int) = {
println(s"student :$name ,age = $age ,score = $i")
}
def Teacher(implicit name: String) = {
println(s"teacher name is = $name")
}
implicit val zs: String = "zhangsan"
implicit val sr: Int = 100
Student(18)
Teacher
}
测试
- 案例2
class Animal(name: String) {
def canFly(): Unit = {
println(s"$name can fly...")
}
}
class Rabbit(xname: String) {
val name = xname
}
object Test extends App {
implicit def rabbitToAnimal(rabbit: Rabbit): Animal = {
new Animal(rabbit.name)
}
val rabbit = new Rabbit("RABBIT")
rabbit.canFly()
}
测试
- 案例3
class Rabbit(s: String) {
val name = s
}
object Test extends App {
implicit class Animal(rabbit: Rabbit) {
val tp = "Animal"
def canFly() = {
println(rabbit.name + " can fly...")
}
}
val rabbit = new Rabbit("rabbit")
rabbit.canFly()
println(rabbit.tp)
}
测试
9 Actor 通讯模型
-
Actor Model是用来编写并行计算或分布式系统的高层次抽象(类似java中的Thread)让程序员不必为多线程模式下共享锁而烦恼,被用在Erlang 语言上, 高可用性99.9999999 % 一年只有31ms 宕机Actors将状态和行为封装在一个轻量的进程/线程中,但是不和其他Actors分享状态,每个Actors有自己的世界观,当需要和其他Actors交互时,通过发送事件和消息,发送是异步的,非堵塞的(fire-andforget),发送消息后不必等另外Actors回复,也不必暂停,每个Actors有自己的消息队列,进来的消息按先来后到排列,这就有很好的并发策略和可伸缩性,可以建立性能很好的事件驱动系统。
-
Actor的特征:
- ActorModel是消息传递模型,基本特征就是消息传递
- 消息发送是异步的,非阻塞的
- 消息一旦发送成功,不能修改
- Actor之间传递时,自己决定决定去检查消息,而不是一直等待,是异步非阻塞的
-
什么是Akka
- Akka 是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和Scala 的 Actor 模型应用,底层实现就是Actor,Akka是一个开发库和运行环境,可以用于构建高并发、分布式、可容错、事件驱动的基于JVM的应用。使构建高并发的分布式应用更加容易。
- spark1.6版本之前,spark分布式节点之间的消息传递使用的就是Akka,底层也就是actor实现的。1.6之后使用的netty传输。
-
案例1
import scala.actors.Actor
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")
}
}
}
}
object Test extends App {
//创建actor的消息接收和传递
val actor = new myActor()
//启动
actor.start()
//发送消息写法
actor ! "i love you !"
actor ! 500
actor ! true
}
测试
- 案例2 Actor与Actor之间通信
import scala.actors.Actor
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!")
}
}
}
}
object Test extends App {
val actor1 = new Actor1()
actor1.start()
val actor2 = new Actor2(actor1)
actor2.start()
}
测试
您的资助是我最大的动力!
金额随意,欢迎来赏!