Scala基石之集合类型

Scala集合学习


总体概览

数组

定长数组

在Scala中在不导包的情况下创建的是定长的集合。

 

val arr = Array[Int](4,5,6)

val arr = new Array[Int](10) // 一定要指定数据类型

var arr = new Array(10) // 这是一种错误的写法,相当于Array[Nothing]

 

变长数组

变长数组的声明一定要导包,Import scala.collection.mutable.ArrayBuffer。

 

var arr1 = ArrayBuffer(“a”,”b”)

var arr1 = ArrayBuffer[String](“a”,”b”) // 注意这个是没有new的

var arr1 = new ArrayBuffer[Int](10) // 这里的这个10是没有意义的,因为是变长数组

一些运算

arr1 += 1 // 在集合的后面追加一个元素

arr1 += (1,2) // 在集合的后面追加一个集合

arr1 ++ arr2 // arr2可以是定长数组也可以是变长数组,重要的是整个数组的连接是基于// copy的原始的数组不会发生改变

 

数组的变换操作

a.map(_ * 10)

a.filter(_ % 2 == 0)

 

List

List也分为可变类型(mutable)与不可变类型(immutable)

 

不可变List

他的特点就是在追加与删除的时候都是基于copy机制的。

 

//几种在头部追加元素的方法(原List不会变):

var list1 = List(1,2,3)

println(0 :: list1)

println(list1.::(0))

println(0+: list1)

println(list1 .+:(0))

// list的连接

list ++ : list2

 

可变List

导包: import scala.collection.mutable.ListBuffer

var list3 = ListBuffer(1,2,3)

    list3 += 4 // 改变了原有的集合

    var list4 = new ListBuffer[Int]()

    list3 ++ list4 // 创建了新的集合

    list3 :+ 8 //创建了新的集合

    list3.map(_* 10)

    println(list3) // 原来的集合还是不变的

   

    list3.map{// 只打印一次hello

        println("hello")

        _*10

    }

    list3.map{// 会打印4次hello

      e => println("hello")

      e * 10

    }

 

Map

同样Map集合也分为可变与不可变两种类型。以下为两种不同的示例:

 

在默认情况下创建的集合为不可变Map,当引入import scala.collection.mutable.Map的时候当前scala文件下的所有的Map都是可变的Map所以在一个scala文件下想使用两种类型的Map的时候需要使用scala.collection.mutable.Map(("z",90),("l",80))创建方式。

 

//import scala.collection.mutable.Map

object MapTest {

  def main(args: Array[String]): Unit = {

    val score = Map("z" -> 90,"l" -> 80)

    val score1 = Map(("z",90),("l",80))

    // 取值

    println(score("z")) 

    // 带有默认值的取值,这个可以部分代替contains,因为map在取不到值的时候会报错

    println(score1.getOrElse("c", 100))

    // 修改值,在不可变类型下以下语句会报错

//    score("z") = 88

    // 以下为强制创建可变类型的Map,在修改map的时没有当前的键的时候会将这一个Entry加入这个集合

    // Map(z -> 0, l -> 80, f -> 8)

    val score3 = scala.collection.mutable.Map(("z",90),("l",80))

    score3("z") = 0

    score3("f") = 8

    println(score3)

    // 以下为专门添加语法,需要注意的是score +=("z",90)这种语法是不行的

    score3 += ("o" -> 90)

    // 删除

    score3 -= "o"

    // 遍历

    for ((k,v) <- score) {

      println(k + ":" + v)

    }

   

  }

}

 

元组

基本使用

不同数据类型对象的集合。以下为元组的基本使用

object TupleTest {

  def main(args: Array[String]): Unit = {

    // 默认的Tuple,存放不同的数据类型

    val t = ("awsl",9,Map())

    // 元组中的元素是无法修改的

    // 创建元祖

    // 以下创建方式很像Map可以通过名字直接访问,注意是逗号

    val t4,(a,b,c) = ("awsl",9,Map())

    // 直接的创建方式,Tuple3是默认的元祖类,当前的元祖的最长长度是22

    val t5 = new Tuple3(1,2,3)

    // 遍历

    t5.productIterator.foreach(println)

  }

}

 

拉链操作

就像拉链一样将两个集合合并成一个元组的数组。

 

object ZipTest {

  def main(args: Array[String]): Unit = {

    // 理想状态下的拉链操作

    val a = Array(1,2,3)

    val b = Array("Java","Python","Scala")

    val c = a.zip(b)

    c.foreach(x => println(x._1,x._2))

    // 在拉链操作进行时如果元素的值不同的时候会报错,除非指定默认值

    val d = Array(1,2,3,4)

    val x = "a"

    val y = "b"

    // 以下为核心,当a为空的时候用x来替补,d为空的时候用y来替补

    val e = a.zipAll(d, x, y)

    e.foreach(x => println(x._1,x._2))// (1,1)(2,2)(3,3)(a,4)

    // 解链操作,解拉链之后会有(Any, Any)) => (T1, T2),

    e.unzip._1.foreach(println) // 1 2 3 a

  }

}

 

Set集合

依然分为可变与不可变,规则与Map一样。以下为简单操作。

 

object SetTest {

  def main(args: Array[String]): Unit = {

    val set1 = Set(1,2,3)

    println(set1 + 4)  // 新的集合

    println(set1) // Set(1, 2, 3)

    // 取头

    set1.head

    // 去尾

    set1.tail

    // 取交集

    val set2 = Set(3,4,5)

    println(set1.intersect(set2)) // Set(3)

    // 并集,创建一个新的集合

    println(set1 ++ set2)

  }

}

 

集合中的重要函数

flatMap

/**

     * 第一个重要的函数就是flatten,就上把嵌套的数据结构中的元素直接拿出来

     * 而flatMap就相当于flatten + Map

     *

     * 场景,现在要将集合A("a","s","d")中的元素转换为大写然后将大小写字母都装进一个集合中

     */

    val a = List("a","s","d")

    val b = a.map(e => List(e,e.toUpperCase()))

    println(b)

    println(b.flatten)

    /*

     * List(List(a, A), List(s, S), List(d, D))

       List(a, A, s, S, d, D)

     * */

    println(a.flatMap(ch => List(ch,ch.toUpperCase())))

    // List(a, A, s, S, d, D)

 

需要注意的是这个是集合的方法不是数组的方法。

 

forAll

判断集合中所有的元素是否都满足一个条件

val c = List(1,2,3,4)

println(c.forall(x => x > 0)) // true

println(c.forall(x => x < 4)) // false

 

reduceLeft & reduceRight

// reduceLeft 和 reduceRight

    val list1 = List(1,2,3,4)

    val res = list1.reduceLeft(_ + _)

    println(res)

    val res1 = list1.reduceLeft(_ - _)

    println(res1) // 1 - 2 - 3 - 4 = -8

    println(list1.reduceRight((x,y) => x - y)) // 4 - 3 - 2 - 1 = -2

 

注意:reduceLeft与reduceRight他们两个的顺序,这一点至关重要。

 

flodLeft&flodRight

flodLeft与reduceLeft相比只是多了一个初始值。

println(list1.foldLeft(10)(_ + _)) // 20,原始值为10