Scala入门第二篇-数据结构

这一节主要介绍Scala中的数据结构:

  • Seq
  • Set
  • Map

集合特质

scala同时支持可变集合和不可变集合,不可变集合从不可变,可以安全的访问
两个主要的包

  • 不可变集合:scala.collection.immutable
  • 可变集合 :scala.collection,mutable

scala优先采用不可变集合,集合主要分为三大类:序列(seq)集(set)映射(map)

  • seq 是一个有先后次序的值得序列,IndexedSeq能够通过整形下标快速得访问元素
  • Set是一个没有先后次序得值集合,在SortedSort中,元素以某种形式排过序的顺序被访问。
  • Map是一组键值对偶,Sorted按照键的排序访问其中的实体

每个Scala集合特质或者类都带有一个Apply方法的伴生对象(类似于静态方法),这个apply方法可以用来构建该集合中的实体,这是统一创建原则.
在这里插入图片描述

Seq

数组Array

下面的命令在命令行进入scala测试:

// 定长数组
val nums = new Array[Int](10)

val s = Array("Hello", "World")
s(0) = "Goodbye"
s


// 变长 数组缓冲
import scala.collection.mutable.ArrayBuffer

val b = ArrayBuffer[Int]()
val b2 = new ArrayBuffer[Int] // If you use new, the () is optional

b += 1
b += (1, 2, 3, 5)
b ++= Array(8, 13, 21)

// 删除最后5个元素
b.trimEnd(5)
b

// 在第三个位置插入6
b.insert(2, 6)
b

// 在第三个位置插入 7、8、9
b.insert(2, 7, 8, 9)
b

// 删除第三个元素
b.remove(2)
b

// 删除从第三个位置开始的3个元素
b.remove(2, 3)
b

// 变长数组与不变数组之间的转换
val a1 = b.toArray
a1.toBuffer

// 数组遍历
val a = Array(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)

//  下标访问
for (i <- 0 until a.length)
  println(i + ": " + a(i))

// 产生一个Range
0 until a.length

// 产生一个Range,以2为间隔
0 until (a.length, 2)

// Range倒转
(0 until a.length).reverse

// a 遍历
for (elem <- a)
  println(elem)

// a 索引
for (i <- a.indices)
  println(i + ": " + a(i))

多维数组

// 多维数组 3行4列
val matrix = Array.ofDim[Double](3, 4) // An array of arrays

val row = 0
val column = 2

matrix(0)(2) = 17.29

matrix.length 
matrix(row) // An array
matrix(row).length 

val triangle = new Array[Array[Int]](10)

for (i <- triangle.indices) 
  triangle(i) = new Array[Int](i + 1)

triangle(0)(0) = 1

for (i <- 1 until triangle.length) {
  triangle(i)(0) = 1
  triangle(i)(i) = 1
  for (j <- 1 until triangle(i).length - 1) 
    triangle(i)(j) = triangle(i - 1)(j - 1) + triangle(i - 1)(j)
}

for (row <- triangle) {
  for (elem <- row) print(elem + " ") 
  println()
}

与Java操作

// 和Java的互操作

import scala.collection.JavaConverters._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

val command = ArrayBuffer("ls", "-al", "/")
// ProessBuilder是java方法
val pb = new ProcessBuilder(command.asJava) // Scala to Java

val cmd : mutable.Buffer[String] = pb.command().asScala // Java to Scala

cmd == command

映射(Map)

映射就是key-value的集合,类似于Java中的Map

  • 注意:不可变映射也可以调用方法,只不过产生新的映射,新的映射和老的映射共享大部分结构,可变映射是在原映射的基础上进行修改.


// 不可变构造映射
val scores = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
// 可变映射
val scores1 = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
// 空映射
val scores2 = new scala.collection.mutable.HashMap[String, Int]
// 对偶
"Alice" -> 10
// 对偶元组
val scores3 = Map(("Alice", 10), ("Bob", 3), ("Cindy", 8))

// 获取值
val bobsScore = scores("Bob")

// contains检测
val fredsScore = if (scores.contains("Fred")) scores("Fred") else 0

// 可以用getOrElse替换检测
scores.getOrElse("Bob", 0)

// 显示调用get,获得Option   Some  None
scores.get("Bob")//获取的是 Option[Int] = Some(1)
scores.get("Bob").get//获取对应的值 value
scores.get("Fred")  //获取到的是Option[Int] = None


// 设置值
scores1("Bob")= 11
scores1("Fred2")=7
scores1


scores1 += ("Bob" -> 10, "Fred" -> 7)

scores1 -= "Alice"

// 不可变映射不能修改,但能够产生新映射
val newScores = scores + ("Bob" -> 10, "Fred" -> 7) // New map with update

// 遍历
for ((k, v) <- map5) println(k + " is mapped to " + v)

// Key的Set集合
scores.keySet

// 遍历value
for (v <- scores.values) println(v)


// 产生新的Map
for ((k, v) <- scores) yield (v, k)

// 排序
val scores4 = scala.collection.immutable.SortedMap("Alice" -> 10,
  "Fred" -> 7, "Bob" -> 3, "Cindy" -> 8)

// 双向链表HashMap
val months = scala.collection.mutable.LinkedHashMap("January" -> 1,
  "February" -> 2, "March" -> 3, "April" -> 4, "May" -> 5,
  "June" -> 6, "July" -> 7, "August" -> 8, "September" -> 9,
  "October" -> 10, "November" -> 11, "December" -> 12)

元组(tuple)

元组是不同类型的值的聚集
注意

  • 元组是从1开始的,可以把t1._2 改写成 t _2(必须有空格);
  • 元组可以用于函数需要返回不止一个值的情况;
  • 使用元组的原因之一是把多个值绑在自已,以便于他们可以一起被处理
// 元组操作
(1, 3.14, "Fred")

val t = (1, 3.14, "Fred")

val second = t._2

val first = t _1

//变量赋值
val (first1, second1, third) = t

val (first2, second2, _) = t


// 拉链操作
val symbols = Array("zhangsan", "lisi", "wangwu")
val counts = Array(2, 10, 2)
val pairs = symbols.zip(counts)

for ((s, n) <- pairs) print(s * n)

symbols.zip(counts).toMap

队列Queue

队列是先进先出的

val q1 = new scala.collection.mutable.Queue[Int]

//追加元素
q1 += 1

q1 += 2

//追加多个元素并返回队列
q1 ++= List(3, 4)

//返回并从队列删除第一个元素
q1.dequeue()

//追加多个元素,返回类型为Unit
q1.enqueue(5, 6, 7)

q1

//队列首部
q1.head

//队列尾部
q1.tail

堆栈Stack

堆栈是先进后出的

val s = new scala.collection.mutable.Stack[Int]()

//入栈
s.push(1)

//入栈多个元素
s.push(2, 3, 4)

//出栈
s.pop()

s

s.push(5)

//取栈顶元素而不出栈
s.top

s

List

  • 不可变序列
    在Scala中列表要么为空(Nil表示空列表) 要么是一个head元素加上一个tail列表。
  • 9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表
    注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))

list常用的操作符:

  • +: (elem: A): List[A] 在列表的头部添加一个元素
  • :: (x: A): List[A] 在列表的头部添加一个元素
  • :+ (elem: A): List[A] 在列表的尾部添加一个元素
  • ++[B](that: GenTraversableOnce[B]): List[B] 从列表的尾部添加另外一个列表
  • ::: (prefix: List[A]): List[A] 在列表的头部添加另外一个列表
  • val left = List(1,2,3)
  • val right = List(4,5,6)
  • //以下操作等价
  • left ++ right // List(1,2,3,4,5,6)
  • right.:::(left) // List(1,2,3,4,5,6)
  • //以下操作等价
  • 0 +: left //List(0,1,2,3)
  • left.+:(0) //List(0,1,2,3)
  • //以下操作等价
  • left :+ 4 //List(1,2,3,4)
  • left.:+(4) //List(1,2,3,4)
  • //以下操作等价
  • 0 :: left //List(0,1,2,3)
  • left.::(0) //List(0,1,2,3)

不可变集合

object  MuList{
//做命令行输入
  def main(args: Array[String]): Unit = {

     //创建一个比可变的集合
    val list1 = List (1,2,3)

    //另一种定义方式
    val list2 = 1 :: 2 :: 3 :: Nil

    //获取头部元素
    val first = list1.head

    //获取头部意外的其他元素,如果只有一个元素就会获得nil
    val tail = list1.tail

    println(list2.head + "----" + list2.tail)

    //将0插入到list1前面生成一个新的list
    val list3 = 0 :: list1 //添加到头部
    val list4 = list1.:: (0) //添加到头部
    val list5 = 0 +: list1 //添加到头部
    val list6 = list1.+:(0) //添加到头部


    //将一个元素添加到list的尾部
    val list7 = list1 :+ 9
    val list0 = List(4,5,6)
     //将两个list合并成一个新的list
    val list8 = list0 ++ list1

    //将list1 放到list0前面
    val list9 = list0 ++: list1

    val list10 = list1.:::(list0)

  }

}

可变长的集合

//构建一个可变列表,初始有3个元素1,2,3
  val lst0 = ListBuffer[Int](1,2,3)
  //创建一个空的可变列表
  val lst1 = new ListBuffer[Int]
  //向lst1中追加元素,注意:没有生成新的集合
  lst1 += 4
  lst1.append(5)

  //将lst1中的元素最近到lst0中, 注意:没有生成新的集合
  lst0 ++= lst1

  //将lst0和lst1合并成一个新的ListBuffer 注意:生成了一个集合
  val lst2= lst0 ++ lst1

  //将元素追加到lst0的后面生成一个新的集合
  val lst3 = lst0 :+ 5

  //删除元素,注意:没有生成新的集合
  val lst4 = ListBuffer[Int](1,2,3,4,5)
  lst4 -= 5

  //删除一个集合列表,生成了一个新的集合
  val lst5=lst4--List(1,2)

  //把可变list 转换成不可变的list 直接加上toList
  val lst6=lst5.toList

  //把可变list 转变数组用toArray
  val lst7=lst5.toArray

Set

Set代表一个没有重复元素的集合;将重复元素加入Set是没有用的,而且 Set 是不保证插入顺序的,即 Set 中的元素是乱序的。
定义:val set=Set(元素,元素,…)

不可变Set

//定义一个不可变的Set集合
scala> val set =Set(1,2,3,4,5,6,7)
set: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)

//元素个数
scala> set.size
res0: Int = 7

//取集合最小值
scala> set.min
res1: Int = 1

//取集合最大值
scala> set.max
res2: Int = 7

//将元素和set1合并生成一个新的set,原有set不变
scala> set + 8
res3: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 8, 4)

scala> val set1=Set(7,8,9)
set1: scala.collection.immutable.Set[Int] = Set(7, 8, 9)

//两个集合的交集
scala> set & set1
res4: scala.collection.immutable.Set[Int] = Set(7)

//两个集合的并集
scala> set ++ set1
res5: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 9, 2, 7, 3, 8, 4)

//在第一个set基础上去掉第二个set中存在的元素
scala> set -- set1
res6: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

//返回第一个不同于第二个set的元素集合
scala> set &~ set1
res7: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)


//计算符合条件的元素个数
scala> set.count(_ >5)
res8: Int = 2

/返回第一个不同于第二个的元素集合。&~
scala> set.diff(set1)
res9: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

/返回第一个不同于第二个的元素集合
scala> set1.diff(set)
res10: scala.collection.immutable.Set[Int] = Set(8, 9)

//取子set(2,5为元素位置, 从0开始,包含头不包含尾)
scala> set.slice(2,5)
res11: scala.collection.immutable.Set[Int] = Set(6, 2, 7)

//迭代所有的子set,取指定的个数组合
scala> set1.subsets(2).foreach(x=>println(x))
Set(7, 8)
Set(7, 9)
Set(8, 9)

可变长的set

//导入包
scala> import scala.collection.mutable
import scala.collection.mutable
//定义一个可变的Set
scala> val set1=new HashSet[Int]()
set1: scala.collection.mutable.HashSet[Int] = Set()

//添加元素
scala> set1 += 1
res1: set1.type = Set(1)

//添加元素  add等价于+=
scala> set1.add(2)
res2: Boolean = true
scala> set1
res3: scala.collection.mutable.HashSet[Int] = Set(1, 2)

//向集合中添加元素集合
scala> set1 ++=Set(1,4,5)
res5: set1.type = Set(1, 5, 2, 4)

//删除一个元素
scala> set1 -=5
res6: set1.type = Set(1, 2, 4)

//删除一个元素
scala> set1.remove(1)
res7: Boolean = true
scala> set1
res8: scala.collection.mutable.HashSet[Int] = Set(2, 4)

将函数映射到集合

将一元函数应用于集合中的每一个元素
map应用于集合中的每一个元素,并产生转换后的新元素

flatmap同样应用于集合的每一个元素,对于每一个元素产出一个集合,并将集合中的元素串接起来


// map 映射
names.map(_.toUpperCase) // List("PETER", "PAUL", "MARY")

for (n <- names) yield n.toUpperCase

def ulcase(s: String) = Vector(s.toUpperCase(), s.toLowerCase())

names.map(ulcase)

// flatmap映射
names.flatMap(ulcase)

names.foreach(println)


折叠简化和扫描操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// 部分化简操作
List(1, 7, 2, 9).reduceLeft(_ - _)

List(1, 7, 2, 9).reduceRight(_ - _)


// 折叠操作
List(1, 7, 2, 9).foldLeft(0)(_ - _)
// 可以用一下方式来表示 foldLeft
(0 /: List(1, 7, 2, 9))(_ - _)



val freq = scala.collection.mutable.Map[Char, Int]()

for (c <- "Mississippi") freq(c) = freq.getOrElse(c, 0) + 1

(Map[Char, Int]() /: "Mississippi") {
  (m, c) => m + (c -> (m.getOrElse(c, 0) + 1))
}

// 扫描操作
(1 to 10).scanLeft(0)(_ + _)

猜你喜欢

转载自blog.csdn.net/weixin_42229056/article/details/83060719
今日推荐