13只怎、scala集合

基本介紹

  • Scala同時支持不可變集合(immutable)可變集合(mutable)啡专, 不可變集合可以安全滴并發(fā)訪問适肠。ps:一般情況下建議使用不可變集合霍衫。
  • scala默認(rèn)采用不可變集合
  • scala集合的三大類: 序列Seq,集Set侯养, 映射Map敦跌,所有的集合都擴(kuò)展自Iterable特質(zhì)。
  • 不可變集合:scala不可變集合沸毁,就是這個集合本身不能動態(tài)變化(類似于java的數(shù)組峰髓,是不可以動態(tài)增長的)。
  • 可變集合:就是這個集合可以動態(tài)變化的(類似于ArrayList息尺,是可以動態(tài)增長的)携兵。
  • 繼承關(guān)系圖:


    scala的不可變集合繼承關(guān)系圖

    scala的可變集合繼承關(guān)系圖

數(shù)組-定長數(shù)組

package com.scala.test

object Test {
  def main(args: Array[String]): Unit = {
    // 1、數(shù)組-定長數(shù)組:使用new的方式
    val arr1 = new Array[Int](10) // 等價于 int[] intArr = new int[10]
    arr1(2) = 1000 // 數(shù)組的訪問及元素內(nèi)容的修改用小括號

    // 2搂誉、數(shù)組-定長數(shù)組:使用apply函數(shù), 定義的同時賦值
    val arr2 = Array(1, 2, "hello") // 泛型是類型推到

    // 3徐紧、遍歷數(shù)組1:直接訪問每個元素, 類似于java的增強(qiáng)的for循環(huán):for(int arr : arr2)
    for (arr <- arr2) {
      println(arr)
    }

    // 4、遍歷數(shù)組2:使用下標(biāo)訪問, 類似于java的for循環(huán):for(int i = 0; i < arr2.length; i++)
    for (idx <- arr2.indices) {
      println(arr2(idx))
    }

    // 5炭懊、scala特有的遍歷方式:將數(shù)組中的每一個元素作用于一個函數(shù)
    arr2.foreach(println)
  }
}
  • 代碼說明:略

數(shù)組-變長數(shù)組

package com.scala.test

import scala.collection.mutable.ArrayBuffer

object Test {
  def main(args: Array[String]): Unit = {
    // 1并级、變長數(shù)組:變長的數(shù)組, 有點(diǎn)兒類似于java的ArrayList
    val arr1 = ArrayBuffer[Int]()
    arr1.append(1) // 注意:每次append一次,就在底層重新分配空間侮腹,進(jìn)行擴(kuò)容嘲碧, 然后內(nèi)存地址也會發(fā)生變化,生成新的ArrayBuffer
    arr1.append(3, 5) // 追加元素, append函數(shù)參數(shù)是可變參數(shù), 可以直接追加多個元素父阻,類似于java的ArrayList的add方法
    arr1 += (7, 9) // 這也可以追加元素
    arr1 ++= ArrayBuffer(2, 4, 6) // 把另一個數(shù)組中的元素全部追加到當(dāng)前數(shù)組, 同樣可以看出ArrayBuffer有apply函數(shù)

    println(arr1(0)) // 查詢元素:使用小括號

    arr1(1) = 5 // 修改指定下標(biāo)的元素值

    arr1.remove(1) // 刪除指定下標(biāo)的元素

    for (arr <- arr1) { // 循環(huán)遍歷
      println(arr)
    }

    // 2愈涩、以上是ArrayBuffer的基本使用:增刪改查, 但實(shí)際上ArrayBuffer有太多太多的函數(shù)了, 以下列舉出一些常用的函數(shù):
    // TODO
  }
}

定長數(shù)組與變長數(shù)組的轉(zhuǎn)換

package com.scala.test

import scala.collection.mutable.ArrayBuffer

object Test {
  def main(args: Array[String]): Unit = {
    val arr1 = Array(1, 3, 5)
    val arr2 = ArrayBuffer(2, 4, 6)

    val arr1_buffer = arr1.toBuffer
    val arr2_array = arr2.toArray

    println(arr1_buffer.isInstanceOf[ArrayBuffer[Int]])
    println(arr2_array.isInstanceOf[Array[Int]])
  }
}
  • 底層是先new出一個目標(biāo)對象來,然后將數(shù)據(jù)拷貝的目標(biāo)對象中加矛,由于使用了數(shù)據(jù)拷貝履婉,可能效率較低。

多維數(shù)組

package com.scala.test

import scala.collection.mutable.ArrayBuffer

object Test {
  def main(args: Array[String]): Unit = {
    val arr = Array.ofDim[Int](3, 4) // 定義一個二維數(shù)組, dim代表是Dimention(即維度), 參數(shù)3和4表示是3行4列
    arr(1)(1) = 10 // 給第1行第1列賦值
    for (row <- arr) {
      for (col <- row) {
        print(col + "\t")
      }
      println()
    }

  }
}

元組

  • 元組可以理解為一個容器斟览,可以存放各種相同或者不同的數(shù)據(jù)毁腿。簡單來說,就是將多個無關(guān)的數(shù)據(jù)封裝為一個整體,稱為元組已烤。
  • 注:元組中最大只能有22個元素鸠窗。
package com.scala.test

object Test {
  def main(args: Array[String]): Unit = {
    // 定義一個元組:定義好后就是一個數(shù)組,只能查詢胯究,不能增刪改
    val t1 = (1, 2, "hello", "world")

    println(t1)
    println(t1._1)
    // 元組的遍歷需要用到迭代器
    for (item <- t1.productIterator) {
      println(item)
    }
  }
}

不可變列表List

  • Scala中的List和java的List不一樣塌鸯,在java中List是一個接口,真正存放數(shù)據(jù)的是ArrayList唐片,而Scala的List可以直接存放數(shù)據(jù),就是一個object涨颜,默認(rèn)情況下费韭,Scala的List的是不可變得,List屬于序列Seq庭瑰。
package com.scala.test

object Test {
  def main(args: Array[String]): Unit = {
    // 在Scala中, List就是不可變的, 所以導(dǎo)入的是scala.collection.immutalbe.List
    // 如果想要使用可變的List, 請使用ListBuffer
    // List是存在于scala的包對象中的, 而scala就已經(jīng)默認(rèn)引入了scala包(類似于java的lang包), 所以List不需要import
    val list1 = List(1, 2, 3, "hello", "world")
    println(list1)
    println(list1(1)) // List是Seq下的, 所以是可以用下標(biāo)的
    val list2 = Nil // Nil也是定義在scala的包對象中的, 所以也不需要引入, Nil等價于List()
    println(list2)

    // List列表元素的追加: 這里的追加不是真正的在原先的list上追加星持,而是會返回一個新的列表對象
    val list3 = Nil :+ 1 :+ "hello"
    val list4 = "hello" +: 1 +: Nil
    // 從上面兩個語句看出:
    // 0、":+"是往列表的最后添加, 而"+:"永遠(yuǎn)是往列表的首位添加
    // 1弹灭、和冒號(即":")挨著的一定是List, 和加號(即"+")挨著的是元素
    // 2督暂、支持鏈?zhǔn)阶芳釉?    // 3、每一次追加都生成新的列表, 所以可能效率上有點(diǎn)兒慢
    println(list3)
    println(list4)

    // list列表追加另一個list, 將另一個list當(dāng)做一個元素追加到當(dāng)前l(fā)ist中
    // 是從有往左運(yùn)行的, 即使將元素或者list追加到另一個List中, 所以::的右邊一定是個List
    // val list_err = List("1", "2", 3) :: 9 // 這句話會報錯, 因?yàn)闊o法把一個list追加到一個Int類型中
    val list_ok = 9 :: List("1", "2", 3) // 這句話是OK的穷吮,因?yàn)榭梢园岩粋€Int類型元素追加到List中
    val list5 = 4 :: 5 :: List("tom", "jerry") :: list3 :: list4 :: Nil
    println(list_ok)
    println(list5)

    // list列表追加另一個list的全部元素:支持一個鏈?zhǔn)秸{(diào)用逻翁,且":::" 可以和 "::" 一起使用
    // ::: 這個符號的兩邊一定要都是List才行
    // val list_err = 9 ::: List("1", "2", 3) // 這句話會報錯, 因?yàn)樾枰獙⒆筮叺膌ist進(jìn)行flat放入到右邊list中,而Int無法flat
    val list_ok2 = Nil ::: List("1", "2", 3) // 這句話OK, 因?yàn)閮蛇叾际荓ist,即使是個空List
    println(list_ok2)
    val list6 = List("tom", "jerry") ::: list3 ::: list4 :: List("scala", "spark") ::: Nil
    println(list6)
  }
}
  • 從上面代碼可以看到一個現(xiàn)象:追加元素的符號有"+:"捡鱼、":+"八回、"::、":::"驾诈; 但是沒有諸如"+="或"++="

可變列表ListBuffer

package com.scala.test

import scala.collection.mutable.ListBuffer

object Test {
  def main(args: Array[String]): Unit = {
    // 直接用applay函數(shù)初始化一個ListBuffer, 需要導(dǎo)入包
    val lb1 = ListBuffer(1, 2, "hello", "world")


    // 遍歷
    for (item <- lb1) {
      println(item)
    }

    // 追加元素: 可以追加1個或多個
    lb1.append("tom")
    lb1.append("scala", "spark")
    lb1 += 4
    lb1 += (4, 5, 6)
    lb1 += ListBuffer("a", "b") // 將整體作為一個元素添加到lb1中
    println(lb1)

    // 以上都是對lb1直接操作增加內(nèi)容缠诅,而以下操作完會直接生成新的的ListBuffer, 且不改變lb1
    val lb2 = lb1 :+ 5
    val lb3 = 5 +: lb1
    println(lb1)
    println(lb2)
    println(lb3)

    // 對lb1追加兩一個ListBuffer里的全部元素
    lb1 ++= lb2
    println(lb1)

    // ++ 符號, 生成新的ListBuffer
    val lb4 = lb1 ++ lb2
    println(lb1) // lb1本身不變
    println(lb4) // 返回了新的ListBuffer

    println("----------移除元素------------")
    lb1.remove(2) // 移除下標(biāo)為2的元素
    println(lb1)
  }
}
  • 看上述代碼,總結(jié)出一個問題乍迄,如果是修改ListBuffer本身管引,那么就是帶等于號的(例如:+= 和 ++=),其他的(例如:++ 和 :+ 和 +:)都是會生成新的ListBuffer闯两。

隊(duì)列Queue

  • 隊(duì)列是個有序列表褥伴,在底層可以用數(shù)組或者鏈表來實(shí)現(xiàn)。
  • 其輸入和輸出要遵循先入先出的原則生蚁。
  • 在scala中噩翠,設(shè)計(jì)者已經(jīng)給我們提供了隊(duì)列類使用。
  • scala.collection.mutable.Queue 和 scala.collection.immtable.Queue邦投, 但是一般來說伤锚,我們在開發(fā)中通常使用可變集合中的隊(duì)列。
package com.scala.test

import scala.collection.mutable

object Test {
  def main(args: Array[String]): Unit = {
    val queue1 = mutable.Queue(1, 2, 3)
    println(queue1)

    queue1 += 4
    queue1 ++= List(5, 6, 7)

    queue1.dequeue() // 從最開始取出一個元素
    queue1.enqueue(8, 9, 10) // 往隊(duì)列尾部追加元素

    for (item <- queue1) {
      println(item)
    }
  }
}

映射Map

  • scala的Map,和java類型屯援,也是一個散列表猛们,存儲的也是鍵值(key-value)對。
  • scala中的不可變Map是有序的狞洋,可變Map是無序的弯淘。 一般情況下我們都使用可變的Map。

(1)吉懊、不可變Map

package com.scala.test

object Test {
  def main(args: Array[String]): Unit = {
    val map = Map("a" -> 1, "b" -> 2, "c" -> 3)
    println(map) // 順序不會變
  }
}
  • 不可變Map是不需要引入包的庐橙,可以直接使用
  • 其實(shí)就是一個集合,且是有序集合借嗽, 且集合中的每個元素是Tuple2類型的态鳖。

(2)、 可變Map

package com.scala.test

import scala.collection.mutable

object Test {
  def main(args: Array[String]): Unit = {
    // 創(chuàng)建map的4個方式:前兩個是聲明一個空的map, 后兩個是聲明有初始值的map
    val map0 = new mutable.HashMap[String, String]()
    val map1 = mutable.Map[String, Int]()
    val map2 = mutable.Map("a" -> 1, "b" -> 2)
    val map3 = mutable.Map(("a", 1), ("b", 2))

    map0("c") = "C" // key存在則是更新恶导,否則就是增加
    map0 += ("a" -> "96")
    map1 += ("A" -> 96)
    map2 ++= map1
    println(map0)
    println(map1)
    println(map2)

    // 查詢某個key的值
    println(map0("a"))
    // println(map0("aa")) // 如果找不到對應(yīng)的key, 則會報異常
    println(if (map0.contains("a")) map0("a") else "key不存在") // 可以用contains判斷
    // println(map0.get("a").get) // 如果key存在, 就會返回一個Some(值), 然后再用get函數(shù)取出值; 如果key不存在, 就會返回None; 總之代碼就不會直接拋異常了浆竭。
    println(map0.getOrElse("a", "默認(rèn)值")) // 這個是最推薦用的函數(shù)

    val map4 = map2 ++ mutable.Map("d" -> 4)
    println(map2) // 不帶等于號的++, 就會返回新的Map, 而原先的Map是不變的!
    println(map4)

    // 遍歷Map方式1:
    for ((k, v) <- map2) { // map中的每一個元素都是一元組,且是Tuple2類型的元組
      println(k + "=" + v)
    }

    // 遍歷Map方式2:
    for (k <- map2.keySet) { // 取出每一個key, 循環(huán)key,
      println(k + "=" + map2(k))
    }

    // map的刪除
    map0.remove("c")
    map0 -= "c" // 即使key不存在也不會報錯
  }
}
  • 使用總結(jié):
  1. 如果能確定map有這個key惨寿,那么選擇map(key)是最好的邦泄,速度快;
  2. 如果我們不能確定map是否有這個key裂垦,而且有不同的業(yè)務(wù)邏輯在里面顺囊,使用map.contains()先判斷在處理。
    3.如果只是簡單滴希望得到一個值缸废,使用map.getOrElse("key", "默認(rèn)值")包蓝。

Set

  • scala默認(rèn)是使用的不可變集合,如果想用可變集合企量,需要引用包:mutable.Set测萎。
  • 值無序且不可重復(fù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市届巩,隨后出現(xiàn)的幾起案子硅瞧,更是在濱河造成了極大的恐慌,老刑警劉巖恕汇,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腕唧,死亡現(xiàn)場離奇詭異,居然都是意外死亡瘾英,警方通過查閱死者的電腦和手機(jī)枣接,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缺谴,“玉大人但惶,你說我怎么就攤上這事。” “怎么了膀曾?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵县爬,是天一觀的道長。 經(jīng)常有香客問我添谊,道長财喳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任斩狱,我火速辦了婚禮耳高,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘所踊。我一直安慰自己祝高,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布污筷。 她就那樣靜靜地躺著,像睡著了一般乍赫。 火紅的嫁衣襯著肌膚如雪瓣蛀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天雷厂,我揣著相機(jī)與錄音惋增,去河邊找鬼。 笑死改鲫,一個胖子當(dāng)著我的面吹牛诈皿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播像棘,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼稽亏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了缕题?” 一聲冷哼從身側(cè)響起截歉,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烟零,沒想到半個月后瘪松,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锨阿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年宵睦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墅诡。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡壳嚎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情诬辈,我是刑警寧澤酵使,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站焙糟,受9級特大地震影響口渔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜穿撮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一缺脉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悦穿,春花似錦攻礼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞬沦,卻和暖如春太伊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逛钻。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工僚焦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人曙痘。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓芳悲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親边坤。 傳聞我的和親對象是個殘疾皇子名扛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容