scala04.数据结构(重点)

第4章数据结构(重点练习章节)

4.1主要的集合特质

4.1主要的集合特质
Scala同时支持可变集合和不可变集合,
不可变集合从不可变,可以安全的并发访问。

4.2数组

Scala优先采用不可变集合。
集合主要分为三大类:序列、集、映射
所有集合都扩展自Iterable特质。
对于几乎所有的集合类,Scqla都同时提供了可变和不可变的版本。
Seq是一个有先后次序的值得序列。
IndexedSeq能够通过整形下标快速访问元素。
Set是一个没有先后次序的值集合。
在SortedSort中,元素以某种排过序的顺序被访问。
Map是一组键值对偶,SortedMap按照键的排序访问其中的实体。

4.2.1定长数组

如果需要一个定长数组,可以使用Scala中的Array,Array 以java数组的方式实现。

4.2.2变长数组

变长数组可以使用ArrayBuffer,Java中有ArrayList

4.2.3数组转换

转换动作不会修改原数组,而是产生一个新的数组。

4.2.4多维数组

和Java一样,多维数组通过数组的数组来实现,可以用ofDim方法。

4.2.5和Java数组的互操作

Scala数组是通过Java进行实现的
使用scala.collection.convert.AsJavaConverters
或者AsScalaConverters进行转换

4.3映射

4.3.1映射操作

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

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

4.3.2和Java的互操作

使用JavaConversions进行转换

4.4元组

元组是不同类型的值的聚集
元组使用_1,_2,_3来访问

元组是从1开始不是0;
元组可用于函数需要返回不止一个值得情况

4.5队列

队列是一个先进先出的结构:

4.6堆栈

Stack是一个先进后出的结构

4.7列表

如果List为空,用Nil来表示。

4.8集

集是不重复元素的结合。集不保留顺序,默认是以哈希集实现。

4.9添加去除元素操作符

1.向后(:+)或向前(+:)追加元素到序列当中。
2.添加(+)元素到无先后次序的集合中。
3.用-移除元素。
4.用++和--来批量添加和移除元素。
5.对于列表,优先使用::和.
6.改值操作有+=、++=、-=和--=。
7.对于集合,我更喜欢++、--和--=。
8.我尽量不用++:、+:和++-:。

4.10常用方法

4.11将函数映射到集合

map应用于集合中的每一个元素,并产生转换后的一个新元素。
flatmap同样应用于集合的每一个元素,对于每一个元素产出一个集合,并将集合中的元素串接在一起。

4.12化简、折叠、扫描

将二元函数应用于集合中的元素

4.13拉链操作

作用于两个集合,将对应的元素合并成一个元组。

4.14迭代器

通过iterator方法从集合获得一个迭代器

4.15流(不可变列表)

流Stream只有在需要的时候才会去计算下一个元素

4.16懒视图

:: 返回一个流
view不会缓存数据,每次都要重新计算

4.17与java集合的互操作总结。

4.18线程安全的集合

Scala类库提供了6个并发特质,可以通过混入这些集合,让集合的操作变成同步的

4.19并行集合

Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。

并行集合位于scala.collection.parallel,分immutable和mutable。
通过par关键字将集合转换为一个并行集合
通过ser方法将并行集合转换回串行集合。
注意:在并行任务里面,不要同时更新一个共享变量。

4.20操作符概述

1、如果想在变量名、类名等定义中用保留字,可以用反引号:val‘val'=42
2、这种形式叫中置操作符,A操作符B等同于A.操作符(B)
3、后置操作符,A操作符等同于,A.操作符,如果操作符定义的时候不带()则调用时不能加()
4、前置操作符,+、一、!、~等操作符A等同于A.unary_操作符
5、赋值操作符,A操作符=B等同于A=A操作符B

import java.awt.Font

import org.scalatest.FunSuite

class Chapter03CoreTest extends FunSuite {

  test("core01") {
    //定长数组
    val s = Array("Hello", "World")
    println(s.mkString(","))
    s(1) = "scala"
    //变长数组
    import scala.collection.mutable.ArrayBuffer
    var arrayBuffer = new ArrayBuffer[Int]()
    //元素追加
    arrayBuffer += 1
    arrayBuffer += (2, 3, 4, 5)
    arrayBuffer ++= Array(8, 13, 21)
    println(arrayBuffer.mkString(","))
    //元素移除
    arrayBuffer.trimEnd(2)
    //元素插入
    arrayBuffer.insert(2, 6)
    println(arrayBuffer.mkString(","))

    //变长数组语定长数组之间的互转
    val array1 = arrayBuffer.toArray
    val buffer1 = s.toBuffer
    //数组的遍历
    for (i <- 0 to arrayBuffer.size - 1) println(arrayBuffer(i))
    // 数组通过下标访问
    for (i <- 0 until array1.length)
      println(i + ": " + array1(i))
    //产生一个Range序列
    val range1 = 0 until(4, 1)
    println(range1.reverse)
    // a 遍历
    for (elem <- array1)
      println(elem)

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

  }

  test("core02") {
    // 产生新的数组
    val a = Array(2, 3, 4, 5)
    val result = for (i <- a) yield 2 * i
    //数组转字符串
    println(result.mkString(","))
    //数组排序
    result.sorted
    //快速排序
    scala.util.Sorting.quickSort(result)
    println(result.mkString(","))
    println(result.toString)
    //统计大于0的个数
    println(result.count(_ > 0))
    import scala.collection.mutable.ArrayBuffer
    var buffer = ArrayBuffer(1, 2, 3)
    //追加
    buffer.append(1)
    //追加数组
    buffer.appendAll(ArrayBuffer(1, 2, 3))
    val result2 = Array(1)
    //    result2.copyToArray(result)
    //添加20项 使用-1填充
    result2.padTo(20, -1)
  }
  test("core03") {
    //多维数组 矩阵 3行四列
    val matrix = Array.ofDim[Double](3, 4)
    val row = 0
    val column = 2
    //赋值
    matrix(0)(2) = 18.99
    println(matrix.length)
    println(matrix(row).length)

  }
  test("core04") {
    // scala 和Java的相互操作
    import scala.collection.JavaConversions._
    import scala.collection.mutable
    import scala.collection.mutable.ArrayBuffer

    val command = ArrayBuffer("ls", "-al", "/")
    //    val pb = new ProcessBuilder(command.asJava)
    //    val cmd:mutable.Buffer[String] = pd.command().asScala
    //    assert(cmd == command)
  }
  test("core05") {
    //不可变的map "Jim" -> 10称为对偶
    val map1 = Map("Jim" -> 10, "Bob" -> 3, "lucy" -> 8)
    //可变的map
    val map2 = scala.collection.mutable.Map("Jim" -> 10, "Bob" -> 3, "lucy" -> 8)
    // 空映射
    val scores = new scala.collection.mutable.HashMap[String, Int]
    //对偶元组
    val map3 = Map(("Alice1", 11), ("Alice2", 11), ("Alice3", 11))
    //取值
    println(map1.get("Jim"))
    println(map1.getOrElse("Jim", "0"))
    // contains检测
    val fredsScore = if (scores.contains("Fred")) scores("Fred") else 0
    //设置参数值
    map1("Jim") = 100
    //    map1("Bob")=11
    //遍历map
    for ((k, v) <- map1) println(k + "is mapped to" + v)
    //keyset集合
    val set = map1.keySet
    //遍历所有的value
    for (v <- map1.values) println(v)
    //产生新的Map
    for ((k, v) <- map1) yield (v, k)
    //排序的map
    val map4 = scala.collection.immutable.SortedMap("Alice" -> 10, "Fred" -> 11)
    //双向链表HashMap
    val months = scala.collection.mutable.LinkedHashMap("Jan" -> 1)


  }
  test("core06") {
    //map和Java的相互转换
    import scala.collection.JavaConverters._
    val ids = java.time.ZoneId.SHORT_IDS.asScala

    val props = System.getProperties.asScala
    import java.awt.font.TextAttribute._
    val attrs = Map(FAMILY -> "Serif", SIZE -> 12)
    val front = new Font(attrs.asJava)
  }
  test("core07") {
    //元祖
    val tuple = (1, 2, 3, "Fred")
    //元祖访问
    val second = tuple._2
    //元祖访问
    val first = tuple._1

    //拉链操作
    val symbols = Array("<", "-", ">")
    val counts = Array(2, 10, 2)
    //zip 拉链操作
    val pairs = symbols.zip(counts)
    //遍历
    for ((s, n) <- pairs) println(s * n)
    //拉链操作 转Map
    symbols.zip(counts).toMap
  }
  test("core08") {
    import scala.collection.mutable
    //声明一个队列
    val q1 = new mutable.Queue[Int]()
    //队列追加元素
    q1 += 2
    q1 += 1
    //追加多个元素并返回队列
    q1 ++= List(2, 3)
    //返回并从队列删除第一个元素
    q1.dequeue()
    //追加多个元素 返回Unit
    q1.enqueue(5, 3, 6)
    //头
    print(q1.head)
    //尾
    print(q1.tail)

  }
  test("core09") {

    import scala.collection.mutable
    //声明一个栈
    val s = new mutable.Stack[Int]()
    //入栈
    s.push(1)
    s.push(1, 2)
    //出栈
    s.pop()
    s.push(3)
    //获取栈顶元素
    s.top
  }
  test("core10") {
    //列表
    val digists = List(4, 2)
    //右边结合操作符
    9 :: List(4, 2)

    //NIL表示空列表
    9 :: 4 :: 2 :: Nil

    //    9 :: (4 :: (2 :: Nil))
    sum(List(1, 2, 3))
    sum2(List(1, 2, 3))
    //sum求和
    List(1, 2, 3).sum
  }

  def sum(lst: List[Int]): Int = if (lst == Nil) 0 else lst.head + sum(lst.tail)

  def sum2(lst: List[Int]): Int = lst match {
    case Nil => 0
    case h :: t => h + sum(t)
  }

  test("core11") {
    //set不可重复集合
    var numberSet = Set(1, 2, 3)
    //set 追加元素
    numberSet += 5
    //set 大小
    println(numberSet.size)
    //set 减去元素
    Set(1, 2, 3) - 3
    //set 追加元素
    Set(1, 2, 3) + 1
    //遍历 set
    for (x <- Set(1, 2, 3)) println(x)

  }
  test("core12") {
    //map映射
    val names = List("Peter", "Paul", "Mary")
    //map
    names.map(_.toLowerCase) // List("PETER", "PAUL", "MARY")
    //等价于map操作
    for (n <- names) yield n.toUpperCase()
    //flatMap操作 打平
  }

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

  test("core13") {
    //部分简化操作
    List(1, 2, 3).reduceLeft(_ - _)
    List(1, 2, 3).reduceRight(_ - _)
    //折叠操作
    List(1, 2, 3, 4).foldLeft(0)(_ - _)

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

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

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


  }
  test("core14") {
    val prices = List(1, 2, 3)
    val quantites = List(1, 2, 3)
    prices zip quantites
    //拉链后执行map操作
    (prices zip quantites) map { p => p._1 * p._2 }
    List(1, 2, 3) zip List(1, 2, 3)
    List(1, 2, 3).zipAll(List(10, 2), 0, 2)
    "Scala".zipWithIndex
    "Scala".zipWithIndex.max
    "Scala".zipWithIndex.max._2
    //unzip函数可以将一个元素的列表转换成一个列表的元祖
    "scala".zipWithIndex.unzip
    "scala".zipWithIndex.unzip._1
    "scala".zipWithIndex.unzip._2
  }
  test("core15") {
    //切片操作返回一个迭代器
    val iterator = (1 to 10).sliding(3)
    while (iterator.hasNext) println(iterator.next())
    val iterable2 = (1 to 10).sliding(3)
    //遍历长度
    for (i <- iterable2) print(i)
    //获取长度
    println(iterable2.length)
    //iterable2 会移动指针
    println(iterable2.hasNext)
    //返回迭代器数组
    println(iterable2.toArray)
  }

  // #::返回一个流
  def numsForm(n: BigInt): Stream[BigInt] = n #:: numsForm(n + 1)

  test("core16") {
    val tenOrMore = numsForm(10)
    //尾部
    tenOrMore.tail
    //头部
    tenOrMore.head
    //最后一个元素
    tenOrMore.tail.tail.tail
    //对流执行求值运算
    val squares = numsForm(5).map(x => x * x)
    squares.take(5).force
  }

  def sq(x: Int): Stream[Int] = {
    println(x)
    x * x
  } #:: sq(x + 1)

  test("core17") {
    //view的懒执行 不是很好理解
    //view不会缓存数据,每次都要重新计算
    //    import scala.math._
    val p = (1 to 10).view.map(x => {
      println(x)
      x * x
    })
    p.take(10).mkString(",")
    val p1 = sq(0)
    p1(10)
    p1.take(10).last
  }
  test("core18") {
    //通过par关键字将集合转换为一个并行集合
    (1 to 5).par.foreach { 
      it => println(Thread.currentThread().getName()); print("^" + it)
  }
    val c = (1 to 5).map(_ + 100)
    println(c)
  }
}

你可能感兴趣的:(scala04.数据结构(重点))