Scala 的集合有三大类:
序列 Seq、集 Set、映射 Map
,所有的集合都扩展自 Iterable 特质,在 Scala 中集合有可变(mutable)和不可变(immutable)两种类型。
Seq
是 Java 没有的,我们发现 List 归属到 Seq 了,因此这里的 List 就和 java 不是同一个概念了。IndexedSeq
下的 Vector
。IndexeSeq
。Queue
和 Stack
被归属到 LinearSeq
。SortedMap
,说明 Scala 的 Map 可以支持排序。IndexSeq
和 LinearSeq
的区别[IndexSeq 是通过索引来查找和定位,因此速度快,比如 String 就是一个索引集合,通过索引即可定位] [LineaSeq 是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找,它的价值在于应用到一些。具体的应用场景 (电商网站, 大数据推荐系统 :最近浏览的 10 个商品)]scala
//第一种创建方法
val num = new Array[Int](5)
//赋值,集合元素采用小括号访问
num(1) = 10
//第二种创建方法,在定义数组时,直接赋值//使用 apply 方法创建数组对象
val num2 = Array(1,2,3,4,5,6)
变长数组(声明泛型)
scala
val num = ArrayBuffer[Any](1, "michong", 3.14)
//添加
num.appendAll("hi")
for (i <- num) {
println(i)
}
//删除
num.remove(4)
//修改
num(0) = "hello"
arr1.toBuffer
//定长数组转可变数组arr2.toArray
//可变数组转定长数组scala
package cn.buildworld.scala.day3
object demo2 {
def main(args: Array[String]): Unit = {
//创建元组
val tuple = (1,2,"hello")
//访问元组
//1. 使用 _顺序号
println(tuple._2) // "hello"
//2. 使用
println(tuple.productElement(2)) //下标是从 0 开始计算
//遍历元组
for(i<-tuple.productIterator){
println(i)
}
}
final case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) extends Product3[T1, T2, T3] {
override def toString: String = "(" + _1 + "," + _2 + "," + _3 + ")"
}
}
scala
val list = List(1,2,3)
println(list )
//创建一个空list
val list02 = Nil
println(list02)
//在list后面添加元素
val list03 = list:+4
println(list03)
//在list前面添加元素
val list04 = "hi"+:list
println(list04)
//符号::表示向集合中,新建集合添加元素。从右向左
val list5 = 4 :: 5 :: 6 :: list :: Nil
println(list5)
// ::: 运算符是将集合中的每一个元素加入到空集合中去, ::: 左右两边需要时集合.
val list6 = 4 :: 5 :: 6 :: list ::: Nil
println(list6)
//结果
List(1, 2, 3)
List()
List(1, 2, 3, 4)
List(hi, 1, 2, 3)
List(4, 5, 6, List(1, 2, 3))
List(4, 5, 6, 1, 2, 3)
ListBuffer:ListBuffer 是可变的 list 集合,可以添加,删除元素,ListBuffer 属于序
scala
object demo4 {
def main(args: Array[String]): Unit = {
val list = ListBuffer[Int](1, 2, 3)
list.addOne(4)
list.append(5)
println(list)
list += 6
println(list)
//++ 表示的是加入的是集合中的各个元素
val list2 = list ++ list
println(list2)
list2.remove(0)
println(list2)
}
}
//输出
ListBuffer(1, 2, 3, 4, 5)
ListBuffer(1, 2, 3, 4, 5, 6)
ListBuffer(1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6)
ListBuffer(2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6)
scala.collection.mutable.Queue
和 scala.collection.immutable.Queue
, 一般来说,我们在开发中通常使用可变集合中的队列scala
import scala.collection.mutable
object demo5 {
def main(args: Array[String]): Unit = {
//创建队列
val q1 = new mutable.Queue[Int]
//追加数据
q1+=1
q1+=2
println(q1)
//添加list
q1++=List(3,4)
println(q1)
//取出队列最前面的那个元素
println(q1.dequeue())
println(q1)
//队尾追加元素
q1.enqueue(5,6,7)
println(q1)
//返回队列的第一个元素
println(q1.head)
//返回队列的最后一个元素
println(q1.last)
//返回除第一个元素以外的其他元素的队列
println(q1.tail)
}
}
//结果
Queue(1, 2)
Queue(1, 2, 3, 4)
1
Queue(2, 3, 4)
Queue(2, 3, 4, 5, 6, 7)
2
7
Queue(3, 4, 5, 6, 7)
可变 Map (scala.collection.mutable.Map)
和 不可变 Map(scala.collection.immutable.Map)
。scala
//构造不可变map,输入输出结果一致
val map1 = Map("MiChong" -> 25, "Zz" -> 24, "Alice" -> 18)
println(map1)
//构造可变map
val map2 = scala.collection.mutable.Map("MiChong" -> 25, "Zz" -> 24, "Alice" -> 18)
println(map2)
//创建空的map
val map3 = new mutable.HashMap[String,Int]
println(map3)
//对偶元组,即创建包含键值对的二元组
val map4 = mutable.Map(("A",1),("B",2),("C",3))
println(map4("A"))
scala
object demo7 {
def main(args: Array[String]): Unit = {
val map1 = Map("MiChong" -> 25, "Zz" -> 24, "Alice" -> 18)
//方式1
// 1) 如果 key 存在,则返回对应的值
// 2) 如果 key 不存在,则抛出异常[java.util.NoSuchElementException]
println(map1("Zz"))
//方式2、
// 1.如果 key 存在,则返回 true
// 2.如果 key 不存在,则返回 false
println(map1.contains("Zz"))
//方式3、通过 映射.get(键) 这样的调用返回一个 Option 对象,要么是 Some,要么是 None
// 2) 如果 map.get(key) key 存在返回 some,如果 key 不存在,则返回 None
// 3) 如果 map.get(key).get key 存在,返回 key 对应的值,否则,抛出异常 java.util.NoSuchElementException: None.get
println(map1.get("Zz").get)
//方式4、getOrElse()
//如果 key 存在,返回 key 对应的值。
//如果 key 不存在,返回默认值。在 java 中底层有很多类似的操作。
println(map1.getOrElse("zz","default"))
}
}
scala
import scala.collection.mutable
object demo8 {
def main(args: Array[String]): Unit = {
val map1 = mutable.Map("MiChong" -> 25, "Zz" -> 24, "Alice" -> 18)
//修改和添加
//1) map 是可变的,才能修改,否则报错
//2) 如果 key 存在:则修改对应的值,key 不存在,等价于添加一个 key-val
map1("qjzxzxd")= 22
println(map1)
//添加多个元素
map1 +=("qjzxzxd"->1,"demo2"->2)
println(map1)
}
}
scala
package cn.buildworld.scala.day3
import scala.collection.mutable
object demo8 {
def main(args: Array[String]): Unit = {
val map1 = mutable.Map("MiChong" -> 25, "Zz" -> 24, "Alice" -> 18)
//遍历map
for ((k, v) <- map1) {
println("键:" + k + " 值:" + v)
}
for (k<-map1.keys){}
for(v<-map1.values){}
}
}
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用
scala.collection.mutable.Set
包
scala
package cn.buildworld.scala.day3
import scala.collection.mutable
object demo9 {
def main(args: Array[String]): Unit = {
//不可变
val set1 = Set(1,2,3,4)
println(set1)
//可变
val set2 = mutable.Set(1,2,3,4,"abc")
println(set2)
}
}
//结果
Set(1, 2, 3, 4)
HashSet(1, 2, 3, abc, 4)
scala
//可变
val set2 = mutable.Set(1,2,3,4,"abc")
println(set2)
set2.add(5)
set2 += 6
set2 +=(7)
println(set2)
//结果
HashSet(1, 2, 3, abc, 4, 5, 6, 7)
scala
//可变
val set2 = mutable.Set(1, 2, 3, 4, "abc")
println(set2)
set2.add(5)
set2 += 6
set2 += (7)
println(set2)
set2 -= 2
set2 -= (3)
set2.remove(4)
println(set2)
//结果
HashSet(1, abc, 5, 6, 7)
scala
//可变
val set2 = mutable.Set(1, 2, 3, 4, "abc")
println(set2)
for (x <- set2) {
println(x)
}
序号 | 方法 | 描述 |
---|---|---|
1 | def +(elem: A): Set[A] | 为集合添加新元素,并创建一个新的集合,除非元素已存在 |
2 | def -(elem: A): Set[A] | 移除集合中的元素,并创建一个新的集合 |
3 | def contains(elem: A): Boolean | 如果元素在集合中存在,返回 true,否则返回 false。 |
4 | def &(that: Set[A]): Set[A] | 返回两个集合的交集 |
5 | def &~(that: Set[A]): Set[A] | 返回两个集合的差集 |
6 | def ++(elems: A): Set[A] | 合并两个集合 |
7 | def drop(n: Int): Set[A]] | 返回丢弃前n个元素新集合 |
8 | def dropRight(n: Int): Set[A] | 返回丢弃最后n个元素新集合 |
9 | def dropWhile(p: (A) => Boolean): Set[A] | 从左向右丢弃元素,直到条件p不成立 |
10 | def max: A //演示下 | 查找最大元素 |
11 | def min: A //演示下 | 查找最小元素 |
12 | def take(n: Int): Set[A] | 返回前 n 个元素 |
scala
def main(args: Array[String]): Unit = {
val list = List(3,5,7)
//map中传入一个方法,用于处理list中每个元素
val list2 = list.map(f1)
println(list2)
val f2 = f1 _
println(f2(10))
}
def f1(n:Int): Int = {
n*2
}
flatmap:flat 即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合。
scala
def main(args: Array[String]): Unit = {
val names = List("MiChong")
println(names.flatMap(upper))
}
def upper(string: String):String={
string.toUpperCase
}
filter:将符合要求的数据(筛选)放置到新的集合中
scala
object demo3 {
def main(args: Array[String]): Unit = {
//只保留A开头的单词
val list = List("Ace","Baby","Zoom")
println(list.filter(startA))
}
def startA(string: String): Boolean ={
if(string.startsWith("A")) true else false
}
}
化简:将 二元函数引用于集合中的函数,。
scala
object demo4 {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4,5)
println(list.reduceLeft(sum))
}
//执行相加程序
def sum(n1: Int, n2: Int): Int = {
n1 + n2
}
}
reduceLeft
看做简化版的 foldLeft
scala
object demo5 {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4)
println(list.foldLeft(5)(minus)) //从左到右
println(list.foldRight(5)(minus))//从右到左
}
def minus(n1:Int,n2:Int):Int={
n1 - n2
}
}
扫描,即对做 某个集合的所有元素做 fold 操作,但是会把产生的存 所有中间结果放置于一个集合中保存 // 斐波那契
scala
object demo {
def main(args: Array[String]): Unit = {
val list = (1 to 5).scanLeft(5)(minus)
println(list)
}
def minus(n1:Int,n2:Int):Int={
n1 - n2
}
}
//结果
Vector(5, 4, 2, -1, -5, -10)
case _
分支,类似于 Java 中 default 语句MatchError
=>
等价于 java swtich 的 :
scala
for (ch <- "+-3!"){
ch match {
case '+' => println(ch)
case '-' => println(ch)
//case _ if ... 这里不是默认匹配, 表示忽略 ch , 而是进行后面的 if 匹配.
case _ if ch.toString.equals('3') =>println(ch)
case _ => println("end")
}
}
Array(0)
匹配只有一个元素且为 0 的数组。Array(x,y)
匹配数组有两个元素,并将两个元素赋值为 x 和 y。当然可以依次类推 Array(x,y,z) 匹配数组有 3 个元素的等等….Array(0,_*)
匹配数组以 0 开始scala
for (list <- Array(List(0), List(1, 0), List(88), List(0, 0, 0), List(1, 0, 0))) {
val result = list match {
case 0 :: Nil => "0" // 匹配的 List(0)
case x :: y :: Nil => x + " " + y // 匹配的是有两个元素的 List(x,y)
case 0 :: tail => "0 ..." // 匹配 以 0 开头的后面有任意元素的 List
case x :: Nil => List(x)
case _ => "something else"
}
}
scala
//请返回 (34, 89) => (89,34)
for (pair <- Array((0, 1), (34, 89), (1, 0), (1, 1), (1, 0, 2))) {
val result = pair match { //
case (0, _) => "0 ..." // 表示匹配 0 开头的二元组
case (y, 0) => y //表示匹配 0 结尾的二元组
case (x, y) => (y, x)
case _ => "other" //.默认
}
println(result)
}
scala
def main(args: Array[String]): Unit = {
def main(args: Array[String]): Unit = {
// 模式匹配使用:
val number: Double = 36.0 //Square(6.0)
//说明
//1. 当 number 去和 case Square(n) 时,会进行如下操作
//2. 把 number 传递给 Square unapply(z: Double) 的 z
//3. unapply 被调用,返回一个结果, 返回的结果和程序员的逻辑代码,比如 Some(math.sqrt(z))
//4. 如果返回的结果是 Some 集合,则表示匹配成功 ,如果返回的是 None 则表示匹配失败
//5. 如果匹配成功,就是将 Some(?) 的 值,赋给 case Square(n) 的 n
//6. 这样就等价于将原来对象的构建参数,提取出来,我们将这个过程称为对象匹配, 这个使用很多.
number match {
case Square(n) => println(n) // 6.0
case _ => println("nothing matched")
}
}
}
//说明
//1. unapply 为对象提取器
//2. apply 对象构建器
object Square { //静态性质
def unapply(z: Double): Option[Double] = {
println("unapply 被调用 z =" + z) // 36.0
Some(math.sqrt(z)) // Some(6.0)
}
def apply(z: Double): Double = z * z
}
scala
//抽象类
abstract class Amount
case class Dollar(value: Double) extends Amount
//Currency 样例类
case class Currency(value: Double, unit: String) extends Amount
//NoAmount 样例类
case object NoAmount extends Amount
//样例类依然可以有自己的方法和属性
case class Dog(name: String) {
var age = 10
def cry(): Unit = {
println("小狗汪汪叫~~")
}
}
sealed
,这个超类称之为密封类。在对符合某个条件,而不是所有情况 进行逻辑操作时,使用偏函数是一个不错的选择将包在大括号内的一组 case 语句封装为函数,我们称之为偏函数,它只对会作用于指定类型的参数或指定范围值的参数实施计算,超出范围的值会忽略. 偏函数在 Scala 中是一个特质
PartialFunction
scala
object demo2 {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4,"abc")
val function1 = new PartialFunction[Any,Int] {
override def isDefinedAt(x: Any): Boolean = {
//判断x是否是int类型
x.isInstanceOf[Int]
}
override def apply(v1: Any): Int = {
//将是int类型的元素值+1,然后返回相加之后的值
v1.asInstanceOf[Int] + 1
}
}
// 调用偏函数不能使用 map, 而是 collect
val list2 = list.collect(function1)
println(list2)
}
}
偏函数简化
scala
// 方式1
def f2: PartialFunction[Any, Int] = {
case i: Int => i + 1
}
println(list.collect(f2))
//方式2
val list = List(1, 2, 3, 4, "abc")
val list3 = list.collect {
case i: Int => i + 1
}
println(list3)
没有名字的函数就是匿名函数,可以通过 函数表达式,来设置匿名函数
scala
val add = (a: Int, b: Int) => a + b
println(add(1,2))
能够接受函数作为参数的函数,叫做高阶函数
(higher-order function)
。可使应用程序更加健壮。 高阶函数可以返回一个匿名函数。
scala
object demo3 {
def main(args: Array[String]): Unit = {
println(minusxy(3)(4))
}
def minusxy(x: Int) = {
(y: Int) => x - y
}
}
基本介绍:闭包就是一个函数和与其相关的引用环境(变量/值)组合的一个整体(实体)。
f就是一个闭包
scala
object demo3 {
def main(args: Array[String]): Unit = {
val f = minusxy(10)
println(f(2))
}
def minusxy(x: Int) = {
(y: Int) => x - y
}
}
scala
def eq(s1: String)(s2: String):Boolean={
s1.eq(s2)
}
scala
def main(args: Array[String]): Unit = {
def myRunThread(f1: =>Unit)={
new Thread{
override def run(): Unit = {
f1
}
}
}.start()
myRunThread{
println("start")
Thread.sleep(2000)
println("end")
}
}
scala
object demo2 {
def main(args: Array[String]): Unit = {
val value = new IntMessage[Int](20)
println(value.get)
}
// 在 Scala 定义泛型用[T], s 为泛型的引用
abstract class Message[T](s:T){
def get:T = s
}
//可以构建 Int 类型的 Message
class IntMessage[Int](msg:Int) extends Message(msg)
//String 类型的 Message
class StringMessage[String](msg:String) extends Message(msg)
}
scala 中上界 在 scala 里表示某个类型是 A 类型的子类型,也称上界或上限,使用 <: 关键字,语法如下:
scala
[T <:A] //A 是 T 的上界
//或用通配符:
[_ <:A]
scala 中下界 在 scala 的下界或下限,使用 >: 关键字,语法如下:
scala
[T >: A] //A 是 T 的下界,下限
//或用通配符:
[_ >:A]
Scala 的协变(+),逆变(-),协变 covariant、逆变 contravariant、不可变 invariant