1. 程式人生 > >Spark基礎-列表的使用

Spark基礎-列表的使用

List
object TestList {
  val fruit=List("apples","oranges","pears")
  val nums=List(2,34,4,5)
  val shz3={
    List(	
        List(1,2,34,4),
        List(2,3,4.45),
        List(2,1,4,5))  
  }
  val emp=List()
}

列表和陣列有點相似,但是有兩個根本的區別:1、列表是不可變的,列表的每個元素不能通過賦值進行改變。2、列表的結構是遞迴的(可以認為是連結串列),而陣列不是。
List同一個列表內的元素都必須是相同型別。元素為T的列表寫為List[T],如果以上程式碼全部都寫全是如下的方式:

  val fru:List[String]=List("apples","oranges","pears")
  val nus:List[Int]=List(1,2,3,4)
  val sh3:List[List[Int]]=List(
      List(2,3,4),
      List(34),
      List(12,3,4,5)
      )
   val empty:List[String]=List()

scala的List型別是協變的,意思是對於每一組型別S和T,如果S是T的子型別,那麼List[S]也是List[T]的子型別。List[Noting]是任何型別的子型別。
構建列表的基礎單元只有兩個:Nil和::。Nil表示空列表,::表示追加元素,事實上我們定義List(…)的方式最終都會轉化成定義好的包裝方法::。如上例最終轉化後:

  val fruit="apples"::("oranges"::("pears"::Nil))
  val nums=2::(34::(4::(5::Nil)))
  val shz3=(1::(2::(34::(4::Nil))))::
  (2::(3::(4::(45::Nil))))::
  (2::(1::(4::(5::Nil))))::Nil 
  val emp=Nil

要注意::是右結合的函式。
List的基本操作符:
head:頭元素。
tail:尾元素。
isEmpty:列表是否為空。
我們對Nil使用head方法

scala> Nil.head
java.util.NoSuchElementException: head of empty list
  at scala.collection.immutable.Nil$.head(List.scala:420)
  ... 33 elided

會返回一個異常。
scala同樣有自己的排序方法,srotBy意思是按照什麼元素進行排序
nus.sortBy(x=>x),一個簡單的方式,意思是來一個元素就按照本身進行排序。
對於表示式val fruit=List(“apples”,“oranges”,“pears”)我們可以把他拆解開來:

scala> val List(f,r,t)=fruit
f: String = apples
r: String = oranges
t: String = pears

List(f,r,t)匹配長度為3的列表,並將三個元素分別繫結到模式變數f,r,t中。如果我們不知道列表中有多少變數,更好的方式是使用::來匹配

scala> val f::r::t=fruit
f: String = apples
r: String = oranges
t: List[String] = List(pears)

這種方式的好處是即使我們不知道List有幾個變數依然可以拿到值,如果我們採用前一種方式,只取兩個值會報如下錯誤:

scala> val List(f,r)=fruit
scala.MatchError: List(apples, oranges, pears) (of class scala.collection.immuta
ble.$colon$colon)
  ... 33 elided

和方法::類似的操作符還有:::。不同的是 :::接收的是兩個列表引數。

scala> List(1,2):::List(3,4)
res1: List[Int] = List(1, 2, 3, 4)
scala> List():::List(21,3,4,4,5)
res2: List[Int] = List(21, 3, 4, 4, 5)

同樣的:::也是右結合的。

獲取列表長度:length

scala> (List(2,3,4,5):::List(3)).length
res6: Int = 5

訪問列表:init和last
last只要List尾

scala> List(1,2,3,4).last
res7: Int = 4

init除了尾以外所有List成員。

scala> List(1,2,3,4).init
res8: List[Int] = List(1, 2, 3)

列表反轉reverse

scala> List(1,2,3,4).reverse
res9: List[Int] = List(4, 3, 2, 1)

操作符take、drop、splitAt
scala> List(1,2,3,4).take(2)
res10: List[Int] = List(1, 2)

scala> List(1,2,3,4) drop 2
res11: List[Int] = List(3, 4)

scala> List(1,2,3,4) splitAt 3
res12: (List[Int], List[Int]) = (List(1, 2, 3),List(4))
選擇操作符apply和indices
apply任意位置選取元素,下標從0開始
scala> List(1,2,3,4) apply 3
res13: Int = 4
indices返回List的有效下標:
scala> List(1,2,3,4).indices
res15: scala.collection.immutable.Range = Range(0, 1, 2, 3)
列表扁平化flatten
scala> List("apples","pears").flatten
res16: List[Char] = List(a, p, p, l, e, s, p, e, a, r, s)

列表拉鍊操作,zip
scala> List(1,2,3,4) zip List("a","b","c","d")
res17: List[(Int, String)] = List((1,a), (2,b), (3,c), (4,d))
這個操作注意以少為準,意思是以兩個列表少的為主,如:
scala> List(1,2,3,4) zip List("a","b","c","d","e")
res18: List[(Int, String)] = List((1,a), (2,b), (3,c), (4,d))

scala> List(1,2,3,4) zip List("a","b","c")
res19: List[(Int, String)] = List((1,a), (2,b), (3,c))
我們可以看到第一個操作只做了四個,因為最少的是List(1,2,3,4)只有四個元素,所以出了四個元素的list集合,第二操作因為最少的是後面只有三個,所以zip的結果只產生了三個List元素。
一個最快速的與其自己的下標拉鍊的方法:ZipWithIndex
scala> 
val ll=List("apples","pears","bananas","eggs").zipWithIndex
ll: List[(String, Int)] = List((apples,0), (pears,1), (bananas,2), (eggs,3))
我們可以看到拿了下標直接和自己本身形成了新的List。

對應的解拉鍊:unzip
scala> ll.unzip
res23: (List[String], List[Int]) = (List(apples, pears, bananas, eggs),List(0, 1
, 2, 3))
這個操作也注意需要首先進行zip,然後才能unzip。

List列表的toString和mkString
以元素的形式顯示列表
scala> List("as","bv","ssd").toString
res25: String = List(as, bv, ssd)
mkString有三個引數,使用什麼做頭尾,並且用什麼分割。
scala> List("as","bv","ssd").mkString("[",":","]")
res27: String = [as:bv:ssd]
如果什麼都不放
scala> List("as","bv","ssd").mkString
res28: String = asbvssd
可以放一個引數,如果一個引數就被識別為分割符:
scala> List("as","bv","ssd").mkString(",")
res31: String = as,bv,ssd

列表轉化:iterator、toArray、copyToArray
我們可以在陣列和列表間相互做資料轉化,可以使用List的toArray和array的toList方法:
scala> val tList=List("l","i","s","t")
tList: List[String] = List(l, i, s, t)

scala> val arr=tList.toArray
arr: Array[String] = Array(l, i, s, t)

我們看到arr已經是一個Array型別。
還有一個方法可以把List列表的元素一次複製到目標陣列的指定位置。
使用的語法:List(…) copyToArray(Array[…],下標)
把List放到Array中,從第幾位開始。
scala> val arr=Array(1,2,3,4,5,5,6,7,8)
arr: Array[Int] = Array(1, 2, 3, 4, 5, 5, 6, 7, 8)

scala> List(1,2,3) copyToArray(arr,2)

scala> arr
res38: Array[Int] = Array(1, 2, 1, 2, 3, 5, 6, 7, 8)
步驟首先定義一個array,然後在使用copyToArray。
如果沒有預先定義,使用另一種方式使用。返回結果仔細觀察
scala> val a=List(1,2,3) copyToArray(new ArrayInt,2)
a: Unit = ()
給出的型別是Unit此時雖然操作成功,但是沒有返回結果。因為copyToArray返回結果給了Array本身不返回值。
可以通過迭代iterator訪問:
scala> val it=List(“a”,“b”,“c”,“d”).iterator
it: Iterator[String] = non-empty iterator
scala> it.next
res40: String = a
scala> it.next
res41: String = b

List的高階方法:
列表做對映:map、flatMap、foreach
map對list列表的每個元素使用某種演算法進行操作
List(…)map(函式)

scala> List(2,3,45,6,3.23)map(x=>x+1)
res43: List[Double] = List(3.0, 4.0, 46.0, 7.0, 4.23)

x=>x+1表示的意思是進來一個元素就對他使用x+1這個動作。這個動作可以使用佔位符簡寫。

scala> List(2,3,45,6,3.23)map(_+1)
res44: List[Double] = List(3.0, 4.0, 46.0, 7.0, 4.23)

同樣的還有一些示例操作

scala> List("dfdf","qweqwr","qwewqr","dfdsg","gehhr").map(_.length)
res45: List[Int] = List(4, 6, 6, 5, 5)
scala> List("dfdf","qweqwr","qwewqr","dfdsg","gehhr").map(_.toList.reverse.mkString)
res46: List[String] = List(fdfd, rwqewq, rqwewq, gsdfd, rhheg)

一個和map非常類似的動作flatMap,但是這裡不同的是flatMap會進行扁平化的操作,扁平化就是把所有元素打散的操作。在觀察兩個操作:

scala> val test=List("ddfs","sdf")
test: List[String] = List(ddfs, sdf)

scala> test map(_.toList)
res51: List[List[Char]] = List(List(d, d, f, s), List(s, d, f))

scala> test flatMap(_.toList)
res52: List[Char] = List(d, d, f, s, s, d, f)

首先所有元素經過flatMap首先扁平化,所有元素都別打散,把每個字母都拆開,最後才傳遞給toList形成一個新的List

一個複雜的應用:
結合了range、flatMap、map的綜合應用:

scala> 
val result=List.range(2,7) flatMap(i=>List.range(1,i)map(j=>(i,j)))
result: List[(Int, Int)] = List((2,1), (3,1), (3,2), (4,1), (4,2), (4,3), (5,1),
 (5,2), (5,3), (5,4), (6,1), (6,2), (6,3), (6,4), (6,5))

看一下這段的意義:首先List呼叫了range方法,是建立一個區間列表的方法,表示建立2 util 7的List也就是沒有7,結果交給flatMap,flatMap內的i表示過來的任意一個值,後面的List.range(1,i)表示產生一個List,是1 until i的區間,產生的每一個值進行map操作,map內的j表示來的任意一個值,輸出最開始的i和和現在的值j。
這樣的列表可以使用for迴圈:

scala> 
val result=for(i<-List.range(2,7);j<-List.range(1,i))yield(i,j)
result: List[(Int, Int)] = List((2,1), (3,1), (3,2), (4,1), (4,2), (4,3), (5,1),
 (5,2), (5,3), (5,4), (6,1), (6,2), (6,3), (6,4), (6,5))

foreach對每一個元素進行應用,整個操作返回值是Unit,也就是沒有返回值返回,我們要做的操作返回的結果都在foreach內。

scala> var sum=0
sum: Int = 0
scala> List(1,2,3,4,5).foreach(sum+=_)

scala> List(1,2,3,4,5).foreach(x=>sum+x)

scala> sum
res56: Int = 15

我們可以看到兩種寫法在執行是沒有結果,但是把sum的加操作執行了,sum的值發生了改變。

過濾操作符:filter、partition、find、takeWhile、dropWhile、span。

scala> List(1,23,4,5,6,7,87).filter(_%2==0)
res57: List[Int] = List(4, 6)
返回一個條件為真的列表
scala> List(1,23,4,5,6,7,87).partition(_%2==0)
res58: (List[Int], List[Int]) = (List(4, 6),List(1, 23, 5, 7, 87))
返回兩個列表,一個真一個假。

scala> List(1,23,4,5,6,7,87).find(_%2==0)
res59: Option[Int] = Some(4)
返回滿足條件的第一個元素。

scala> List(1,23,4,5,6,7,87).takeWhile(_%2!=0)
res62: List[Int] = List(1, 23)
返回列表連續滿足後面條件的列表。

scala> List(1,23,4,5,6,7,87).dropWhile(_%2!=0)
res63: List[Int] = List(4, 5, 6, 7, 87)
刪除連續滿足條件的列表。
列表排序操作:sortWith
scala> List(1,23,4,5,6,7,87).sortWith(_>_)
res64: List[Int] = List(87, 23, 7, 6, 5, 4, 1)

表示按照降序排列,要習慣這種佔位符的寫法,簡便很多
_>_正常寫是(x,y)=>x>y,表示來兩個數,按照從打到小順序排列

最後做一個總結,方法和意義如下:
備註:List方法總結
1 def +(elem: A): List[A]
前置一個元素列表
2 def ::(x: A): List[A]
在這個列表的開頭新增的元素。
3 def :::(prefix: List[A]): List[A]
增加了一個給定列表中該列表前面的元素。
4 def ::(x: A): List[A]
增加了一個元素x在列表的開頭
5 def addString(b: StringBuilder): StringBuilder
追加列表的一個字串生成器的所有元素。
6 def addString(b: StringBuilder, sep: String): StringBuilder
追加列表的使用分隔字串一個字串生成器的所有元素。
7 def apply(n: Int): A
選擇通過其在列表中索引的元素
8 def contains(elem: Any): Boolean
測試該列表中是否包含一個給定值作為元素。
9 def copyToArray(xs: Array[A], start: Int, len: Int): Unit
列表的副本元件陣列。填充給定的陣列xs與此列表中最多len個元素,在位置開始。
10 def distinct: List[A]
建立從列表中沒有任何重複的元素的新列表。
11 def drop(n: Int): List[A]
返回除了第n個的所有元素。
12 def dropRight(n: Int): List[A]
返回除了最後的n個的元素
13 def dropWhile(p: (A) => Boolean): List[A]
丟棄滿足謂詞的元素最長字首。
14 def endsWith[B](that: Seq[B]): Boolean
測試列表是否使用給定序列結束。
15 def equals(that: Any): Boolean
equals方法的任意序列。比較該序列到某些其他物件。
16 def exists(p: (A) => Boolean): Boolean
測試謂詞是否持有一些列表的元素。
17 def filter(p: (A) => Boolean): List[A]
返回列表滿足謂詞的所有元素。
18 def forall(p: (A) => Boolean): Boolean
測試謂詞是否持有該列表中的所有元素。
19 def foreach(f: (A) => Unit): Unit
應用一個函式f以列表的所有元素。
20 def head: A
選擇列表的第一個元素
21 def indexOf(elem: A, from: Int): Int
經過或在某些起始索引查詢列表中的一些值第一次出現的索引。
22 def init: List[A]
返回除了最後的所有元素
23 def intersect(that: Seq[A]): List[A]
計算列表和另一序列之間的多重集交集。
24 def isEmpty: Boolean
測試列表是否為空
25 def iterator: Iterator[A]
建立一個新的迭代器中包含的可迭代物件中的所有元素
26 def last: A
返回最後一個元素
27 def lastIndexOf(elem: A, end: Int): Int
之前或在一個給定的最終指數查詢的列表中的一些值最後一次出現的索引
28 def length: Int
返回列表的長度
29 def map[B](f: (A) => B): List[B]
通過應用函式以g這個列表中的所有元素構建一個新的集合
30 def max: A
查詢最大的元素
31 def min: A
查詢最小元素
32 def mkString: String
顯示列表的字串中的所有元素
33 def mkString(sep: String): String
顯示的列表中的字串中使用分隔串的所有元素
34 def reverse: List[A]
返回新列表,在相反的順序元素
35 def sorted[B >: A]: List[A]
根據排序對列表進行排序
36 def startsWith[B](that: Seq[B], offset: Int): Boolean
測試該列表中是否包含給定的索引處的給定的序列
37 def sum: A
概括這個集合的元素
38 def tail: List[A]
返回除了第一的所有元素
39 def take(n: Int): List[A]
返回前n個元素
40 def takeRight(n: Int): List[A]
返回最後n個元素
41 def toArray: Array[A]
列表以一個數組變換
42 def toBuffer[B >: A]: Buffer[B]
列表以一個可變緩衝器轉換
43 def toMap[T, U]: Map[T, U]
此列表的對映轉換
44 def toSeq: Seq[A]
列表的序列轉換
45 def toSet[B >: A]: Set[B]
列表到集合變換
46 def toString(): String
列表轉換為字串

想了解更多大資料的小夥伴歡迎加群947967114