List 是 Scala 中非常重要的一個(gè)數(shù)據(jù)結(jié)構(gòu),其與 Array(數(shù)組) 非常類似,但是 List 是不可變的,和 Java 中的 List 一樣,其底層實(shí)現(xiàn)是鏈表。
scala> val list = List("hadoop", "spark", "storm")list: List[String] = List(hadoop, spark, storm)// List 是不可變scala> list(1) = "hive"<console>:9: error: value update is not a member of List[String]
Scala 中 List 具有以下兩個(gè)特性:
同構(gòu) (homogeneous):同一個(gè) List 中的所有元素都必須是相同的類型;
協(xié)變 (covariant):如果 S 是 T 的子類型,那么 List[S]
就是 List[T]
的子類型,例如 List[String]
是 List[Object]
的子類型。
需要特別說(shuō)明的是空列表的類型為 List[Nothing]
:
scala> List()res1: List[Nothing] = List()
所有 List 都由兩個(gè)基本單元構(gòu)成:Nil
和 ::
(讀作"cons")。即列表要么是空列表 (Nil),要么是由一個(gè) head 加上一個(gè) tail 組成,而 tail 又是一個(gè) List。我們?cè)谏厦媸褂玫?List("hadoop", "spark", "storm")
最終也是被解釋為 "hadoop"::"spark":: "storm"::Nil
。
scala> val list01 = "hadoop"::"spark":: "storm"::Nillist01: List[String] = List(hadoop, spark, storm)// :: 操作符號(hào)是右結(jié)合的,所以上面的表達(dá)式和下面的等同scala> val list02 = "hadoop"::("spark":: ("storm"::Nil))list02: List[String] = List(hadoop, spark, storm)
Scala 支持展開(kāi)列表以實(shí)現(xiàn)模式匹配。
scala> val list = List("hadoop", "spark", "storm")list: List[String] = List(hadoop, spark, storm)scala> val List(a,b,c)=lista: String = hadoopb: String = sparkc: String = storm
如果只需要匹配部分內(nèi)容,可以如下:
scala> val a::rest=lista: String = hadooprest: List[String] = List(spark, storm)
object ScalaApp extends App { val list = List("hadoop", "spark", "storm") // 1.列表是否為空 list.isEmpty // 2.返回列表中的第一個(gè)元素 list.head // 3.返回列表中除第一個(gè)元素外的所有元素 這里輸出 List(spark, storm) list.tail // 4.tail 和 head 可以結(jié)合使用 list.tail.head // 5.返回列表中的最后一個(gè)元素 與 head 相反 list.init // 6.返回列表中除了最后一個(gè)元素之外的其他元素 與 tail 相反 這里輸出 List(hadoop, spark) list.last // 7.使用下標(biāo)訪問(wèn)元素 list(2) // 8.獲取列表長(zhǎng)度 list.length // 9. 反轉(zhuǎn)列表 list.reverse}
indices 方法返回所有下標(biāo)。
scala> list.indicesres2: scala.collection.immutable.Range = Range(0, 1, 2)
take:獲取前 n 個(gè)元素;
drop:刪除前 n 個(gè)元素;
splitAt:從第幾個(gè)位置開(kāi)始拆分。
scala> list take 2res3: List[String] = List(hadoop, spark)scala> list drop 2res4: List[String] = List(storm)scala> list splitAt 2res5: (List[String], List[String]) = (List(hadoop, spark),List(storm))
flatten 接收一個(gè)由列表組成的列表,并將其進(jìn)行扁平化操作,返回單個(gè)列表。
scala> List(List(1, 2), List(3), List(), List(4, 5)).flattenres6: List[Int] = List(1, 2, 3, 4, 5)
對(duì)兩個(gè) List 執(zhí)行 zip
操作結(jié)果如下,返回對(duì)應(yīng)位置元素組成的元組的列表,unzip
則執(zhí)行反向操作。
scala> val list = List("hadoop", "spark", "storm")scala> val score = List(10,20,30)scala> val zipped=list zip scorezipped: List[(String, Int)] = List((hadoop,10), (spark,20), (storm,30))scala> zipped.unzipres7: (List[String], List[Int]) = (List(hadoop, spark, storm),List(10, 20, 30))
toString 返回 List 的字符串表現(xiàn)形式。
scala> list.toStringres8: String = List(hadoop, spark, storm)
如果想改變 List 的字符串表現(xiàn)形式,可以使用 mkString。mkString 有三個(gè)重載方法,方法定義如下:
// start:前綴 sep:分隔符 end:后綴def mkString(start: String, sep: String, end: String): String = addString(new StringBuilder(), start, sep, end).toString// seq 分隔符def mkString(sep: String): String = mkString("", sep, "")// 如果不指定分隔符 默認(rèn)使用""分隔def mkString: String = mkString("")
使用示例如下:
scala> list.mkStringres9: String = hadoopsparkstormscala> list.mkString(",")res10: String = hadoop,spark,stormscala> list.mkString("{",",","}")res11: String = {hadoop,spark,storm}
iterator 方法返回的是迭代器,這和其他語(yǔ)言的使用是一樣的。
object ScalaApp extends App { val list = List("hadoop", "spark", "storm") val iterator: Iterator[String] = list.iterator while (iterator.hasNext) { println(iterator.next) } }
toArray 和 toList 用于 List 和數(shù)組之間的互相轉(zhuǎn)換。
scala> val array = list.toArrayarray: Array[String] = Array(hadoop, spark, storm)scala> array.toListres13: List[String] = List(hadoop, spark, storm)
copyToArray 將 List 中的元素拷貝到數(shù)組中指定位置。
object ScalaApp extends App { val list = List("hadoop", "spark", "storm") val array = Array("10", "20", "30") list.copyToArray(array,1) println(array.toBuffer)}// 輸出 :ArrayBuffer(10, hadoop, spark)
map 與 Java 8 函數(shù)式編程中的 map 類似,都是對(duì) List 中每一個(gè)元素執(zhí)行指定操作。
scala> List(1,2,3).map(_ 10)res15: List[Int] = List(11, 12, 13)
flatMap 與 map 類似,但如果 List 中的元素還是 List,則會(huì)對(duì)其進(jìn)行 flatten 操作。
scala> list.map(_.toList)res16: List[List[Char]] = List(List(h, a, d, o, o, p), List(s, p, a, r, k), List(s, t, o, r, m))scala> list.flatMap(_.toList)res17: List[Char] = List(h, a, d, o, o, p, s, p, a, r, k, s, t, o, r, m)
foreach 要求右側(cè)的操作是一個(gè)返回值為 Unit 的函數(shù),你也可以簡(jiǎn)單理解為執(zhí)行一段沒(méi)有返回值代碼。
scala> var sum = 0sum: Int = 0scala> List(1, 2, 3, 4, 5) foreach (sum = _)scala> sumres19: Int = 15
filter 用于篩選滿足條件元素,返回新的 List。
scala> List(1, 2, 3, 4, 5) filter (_ % 2 == 0)res20: List[Int] = List(2, 4)
partition 會(huì)按照篩選條件對(duì)元素進(jìn)行分組,返回類型是 tuple(元組)。
scala> List(1, 2, 3, 4, 5) partition (_ % 2 == 0)res21: (List[Int], List[Int]) = (List(2, 4),List(1, 3, 5))
find 查找第一個(gè)滿足條件的值,由于可能并不存在這樣的值,所以返回類型是 Option
,可以通過(guò) getOrElse
在不存在滿足條件值的情況下返回默認(rèn)值。
scala> List(1, 2, 3, 4, 5) find (_ % 2 == 0)res22: Option[Int] = Some(2)val result: Option[Int] = List(1, 2, 3, 4, 5) find (_ % 2 == 0)result.getOrElse(10)
takeWhile 遍歷元素,直到遇到第一個(gè)不符合條件的值則結(jié)束遍歷,返回所有遍歷到的值。
scala> List(1, 2, 3, -4, 5) takeWhile (_ > 0)res23: List[Int] = List(1, 2, 3)
dropWhile 遍歷元素,直到遇到第一個(gè)不符合條件的值則結(jié)束遍歷,返回所有未遍歷到的值。
// 第一個(gè)值就不滿足條件,所以返回列表中所有的值scala> List(1, 2, 3, -4, 5) dropWhile (_ < 0)res24: List[Int] = List(1, 2, 3, -4, 5)scala> List(1, 2, 3, -4, 5) dropWhile (_ < 3)res26: List[Int] = List(3, -4, 5)
span 遍歷元素,直到遇到第一個(gè)不符合條件的值則結(jié)束遍歷,將遍歷到的值和未遍歷到的值分別放入兩個(gè) List 中返回,返回類型是 tuple(元組)。
scala> List(1, 2, 3, -4, 5) span (_ > 0)res27: (List[Int], List[Int]) = (List(1, 2, 3),List(-4, 5))
forall 檢查 List 中所有元素,如果所有元素都滿足條件,則返回 true。
scala> List(1, 2, 3, -4, 5) forall ( _ > 0 )res28: Boolean = false
exists 檢查 List 中的元素,如果某個(gè)元素已經(jīng)滿足條件,則返回 true。
scala> List(1, 2, 3, -4, 5) exists (_ > 0 )res29: Boolean = true
sortWith 對(duì) List 中所有元素按照指定規(guī)則進(jìn)行排序,由于 List 是不可變的,所以排序返回一個(gè)新的 List。
scala> List(1, -3, 4, 2, 6) sortWith (_ < _)res30: List[Int] = List(-3, 1, 2, 4, 6)scala> val list = List( "hive","spark","azkaban","hadoop")list: List[String] = List(hive, spark, azkaban, hadoop)scala> list.sortWith(_.length>_.length)res33: List[String] = List(azkaban, hadoop, spark, hive)
上面介紹的所有方法都是 List 類上的方法,下面介紹的是 List 伴生對(duì)象中的方法。
List.range 可以產(chǎn)生指定的前閉后開(kāi)區(qū)間內(nèi)的值組成的 List,它有三個(gè)可選參數(shù): start(開(kāi)始值),end(結(jié)束值,不包含),step(步長(zhǎng))。
scala> List.range(1, 5)res34: List[Int] = List(1, 2, 3, 4)scala> List.range(1, 9, 2)res35: List[Int] = List(1, 3, 5, 7)scala> List.range(9, 1, -3)res36: List[Int] = List(9, 6, 3)
List.fill 使用指定值填充 List。
scala> List.fill(3)("hello")res37: List[String] = List(hello, hello, hello)scala> List.fill(2,3)("world")res38: List[List[String]] = List(List(world, world, world), List(world, world, world))
List.concat 用于拼接多個(gè) List。
scala> List.concat(List('a', 'b'), List('c'))res39: List[Char] = List(a, b, c)scala> List.concat(List(), List('b'), List('c'))res40: List[Char] = List(b, c)scala> List.concat()res41: List[Nothing] = List()
當(dāng)多個(gè) List 被放入同一個(gè) tuple 中時(shí)候,可以通過(guò) zipped 對(duì)多個(gè) List 進(jìn)行關(guān)聯(lián)處理。
// 兩個(gè) List 對(duì)應(yīng)位置的元素相乘scala> (List(10, 20), List(3, 4, 5)).zipped.map(_ * _)res42: List[Int] = List(30, 80)// 三個(gè) List 的操作也是一樣的scala> (List(10, 20), List(3, 4, 5), List(100, 200)).zipped.map(_ * _ _)res43: List[Int] = List(130, 280)// 判斷第一個(gè) List 中元素的長(zhǎng)度與第二個(gè) List 中元素的值是否相等scala> (List("abc", "de"), List(3, 2)).zipped.forall(_.length == _)res44: Boolean = true
上面介紹的 List,由于其底層實(shí)現(xiàn)是鏈表,這意味著能快速訪問(wèn) List 頭部元素,但對(duì)尾部元素的訪問(wèn)則比較低效,這時(shí)候可以采用 ListBuffer
,ListBuffer 提供了在常量時(shí)間內(nèi)往頭部和尾部追加元素。
import scala.collection.mutable.ListBufferobject ScalaApp extends App { val buffer = new ListBuffer[Int] // 1.在尾部追加元素 buffer = 1 buffer = 2 // 2.在頭部追加元素 3 =: buffer // 3. ListBuffer 轉(zhuǎn) List val list: List[Int] = buffer.toList println(list)}//輸出:List(3, 1, 2)
Set 是不重復(fù)元素的集合。分為可變 Set 和不可變 Set。
object ScalaApp extends App { // 可變 Set val mutableSet = new collection.mutable.HashSet[Int] // 1.添加元素 mutableSet.add(1) mutableSet.add(2) mutableSet.add(3) mutableSet.add(3) mutableSet.add(4) // 2.移除元素 mutableSet.remove(2) // 3.調(diào)用 mkString 方法 輸出 1,3,4 println(mutableSet.mkString(",")) // 4. 獲取 Set 中最小元素 println(mutableSet.min) // 5. 獲取 Set 中最大元素 println(mutableSet.max)}
不可變 Set 沒(méi)有 add 方法,可以使用
添加元素,但是此時(shí)會(huì)返回一個(gè)新的不可變 Set,原來(lái)的 Set 不變。
object ScalaApp extends App { // 不可變 Set val immutableSet = new collection.immutable.HashSet[Int] val ints: HashSet[Int] = immutableSet 1 println(ints)}// 輸出 Set(1)
多個(gè) Set 之間可以進(jìn)行求交集或者合集等操作。
object ScalaApp extends App { // 聲明有序 Set val mutableSet = collection.mutable.SortedSet(1, 2, 3, 4, 5) val immutableSet = collection.immutable.SortedSet(3, 4, 5, 6, 7) // 兩個(gè) Set 的合集 輸出:TreeSet(1, 2, 3, 4, 5, 6, 7) println(mutableSet immutableSet) // 兩個(gè) Set 的交集 輸出:TreeSet(3, 4, 5) println(mutableSet intersect immutableSet)
聯(lián)系客服