- List簡介
- 特性
- 建立清單
- 操作
- list的基本操作
- list類的一階方法
- 連接配接
- 長度
- reverse
- apply indices
- zip
- mkString
- list類的高階方法
- foreach
- map
- flatMap
- filter
- partition
- find
- takeWhile dropWhile span
- 論斷forallexists
- 折疊
- 排序
- list對象的方法
List簡介
特性
- 不可變
- 遞歸結構
- 同構(同質)的:元素的類型必須一緻
- 協變的:如果S是T的子類型,那麼List[S]是List[T]的子類型,這點不同于java的泛型
- 空清單為List[Nothing],Nil
建立清單
- 所有的List都是由空清單
和操作符Nil
構造出來的,::
表示從前端擴張清單.::
- 實際上,用形如List(e1,e2,…)的方式建立清單在底層也是使用
和Nil
構造出來的::
scala> List(,,)
res0: List[Int] = List(, , )
scala> ::Nil
res1: List[Int] = List()
scala> ::res1
res2: List[Int] = List(, )
scala> ::res2
res3: List[Int] = List(, , )
操作
list的基本操作
method | DESC |
---|---|
head | List的第一個元素 |
tail | 除了head之外的其他元素組成的List |
isEmpty | List是否為空 |
last | List的最後一個元素 |
init | 除了last之外的其他元素組成的List |
scala> val l1=List(,,,,)
l1: List[Int] = List(, , , , )
scala> l1.tail
res4: List[Int] = List(, , , )
scala> l1.head
res5: Int =
scala> l1.isEmpty
res6: Boolean = false
scala> l1.init
res7: List[Int] = List(, , , )
scala> l1.last
res8: Int =
list類的一階方法
連接配接
清單的連結操作符
:::
和擴充元素操作符
::
一樣都是右結合的,即
xs:::ys:::zs
等價于
xs:::(ys:::zs)
,不過兩個操作數都是List
scala> List(,,):::List(,,)
res9: List[Int] = List(, , , , , )
長度
内部定義:
def length: Int = {
var these = self
var len =
while (!these.isEmpty) {
len +=
these = these.tail
}
len
}
是以,length方法是比較費時的
reverse
反轉list:reverse ,該方法并不是在原地修改list,因為list是不可變的,是以會傳回一個新的list
- drop和take可以了解為更為廣義的tail和init操作
- take(n)傳回清單的前n個元素,
if(n>list.length) return list
- drop(n)傳回除了take(n)之外的所有元素,
if(n>list.length) return Nil
- splitAt(n)在位置n處拆分清單,傳回位元組。等價于
(list.take(n),list.drop(n))
scala> val l1=Range(,).toList
l1: List[Int] = List(, , , , , , , , , )
scala> l1.take()
res10: List[Int] = List(, , )
scala> l1.drop()
res11: List[Int] = List(, , , , , , )
scala> l1.splitAt()
res12: (List[Int], List[Int]) = (List(, , ),List(, , , , , , ))
apply | indices
scala> val l1=Range(,).toList
l1: List[Int] = List(, , , , , , , , , )
scala> l1.apply()
res13: Int =
scala> l1()
res14: Int =
scala> l1.indices
res15: scala.collection.immutable.Range = Range(, , , , , , , , , )
zip
不比對的元素将被遺棄
scala> val l1=Range(,).toList
l1: List[Int] = List(, , )
scala> val l2=List("a","b","c","d")
l2: List[String] = List(a, b, c, d)
scala> l1.zip(l2)
res16: List[(Int, String)] = List((,a), (,b), (,c))
mkString
mkString([start,]seperator[,end])
scala> val l=Range(,).toList
l: List[Int] = List(, , , )
scala> l.mkString("start","|","end")
res17: String = start1|||end
scala> l.mkString("|")
res18: String = |||
list類的高階方法
foreach
周遊list并将傳入的lambda作用于每個元素
内部實作:
@inline final override def foreach[U](f: A => U) {
var these = this
while (!these.isEmpty) {
f(these.head)
these = these.tail
}
}
周遊
val l1 = Range(, ).toList
l1.foreach(e => { print(e + " ") })
l1.foreach(print(_))
等價的java8操作
List<Integer> list = Stream.iterate(, i -> i + ).limit()
.collect(Collectors.toList());
list.forEach(e -> {
System.out.print(e + " ");
});
list.forEach(System.out::print);
求和
val l1 = Range(, ).toList
var sum =
l1.foreach(sum += _)
println(sum)
map
參數f:T=>R,将f作用于每個元素,并傳回類型為R的新清單
構造新list,元素為原list的元素的2倍
l1.map(e => e * )
println(l1)
等價的java8代碼
list.stream().map(e->e*).collect(Collectors.toList());
flatMap
和map類型,但請注意傳回類型
scala> val l=List("tom","cat","apache")
l: List[String] = List(tom, cat, apache)
scala> l.map(_.toList)
res19: List[List[Char]] = List(List(t, o, m), List(c, a, t), List(a, p, a, c, h, e))
scala> l.flatMap(_.toList)
res20: List[Char] = List(t, o, m, c, a, t, a, p, a, c, h, e)
filter
scala> val l=Range(,).toList
l: List[Int] = List(, , , , , , , , , )
scala> l.filter(e=>(e%)==)
res22: List[Int] = List(, , , , )
scala> l.filter(e=>(e&)==)
res24: List[Int] = List(, , , , )
partition
傳回二進制組(符合條件的部分,不符合條件的部分)
scala> val l=Range(,).toList
l: List[Int] = List(, , , , , , , , , )
scala> l.partition(e=>(e%)==)
res26: (List[Int], List[Int]) = (List(, , , , ),List(, , , , ))
find
傳回第一個滿足條件的
scala> l.find(e=>(e%)==)
res27: Option[Int] = Some()
takeWhile | dropWhile | span
- takeWhile(p):傳回能夠滿足p的最長字首組成的list
- dropWhile(p):傳回list中除了takeWhile(n)的部分組成的清單
- span:類似于slitAt結合了take和drop,span結合了takeWhile和dropWhile的結果
scala> val l=List(,,,-,,)
l: List[Int] = List(, , , -, , )
scala> l.dropWhile(_>)
res28: List[Int] = List(-, , )
scala> l.takeWhile(_>)
res30: List[Int] = List(, , )
scala> l.span(_>)
res31: (List[Int], List[Int]) = (List(, , ),List(-, , ))
論斷(forall,exists)
scala> val l=List(,,,-,,)
l: List[Int] = List(, , , -, , )
scala> l.forall(_>)
res33: Boolean = false
scala> l.exists(_>)
res35: Boolean = true
折疊
- 1.foldLeft(/:)
内部實作:
//注意op第一個參數類型為seed的類型
override /*TraversableLike*/
def foldLeft[B](z: B)(@deprecatedName('f) op: (B, A) => B): B = {
var acc = z//z表示初始值,seed
var these = this
while (!these.isEmpty) {
//每次将op作用于目前seed和目前元素并将結果重新指派于seed
acc = op(acc, these.head)
these = these.tail
}
//最終傳回"累加"的結果
acc
}
- 2.foldRight(:\)
内部實作:
//反轉後調用foldLeft
//注意op第二個參數類型為seed的類型
override def foldRight[B](z: B)(op: (A, B) => B): B =
reverse.foldLeft(z)((right, left) => op(left, right))
- 3.fold
内部實作:
//注意op的兩個參數類型相同
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)
求和
val l1 = Range(, ).toList
var sum = l1.foldLeft()((acc, e) => acc + e)
println(sum) //55
sum = l1./:()((acc, e) => acc + e)
println(sum) //55
sum = l1.foldRight()((e, acc) => acc + e)
println(sum) //55
sum = l1.fold()((acc, e) => acc + e)
println(sum) //55
sum = l1.foldLeft()(_ + _)
println(sum) //55
sum = l1./:()(_ + _)
println(sum) //55
sum = ( /: l1)(_ + _) //相當于 l1./:(0)
//sum = (l1 /: 0)(_ + _) //錯誤,相當于0./:(l1)
println(sum) //55
乘積
var pro =
val l1 = Range(, ).toList
pro = l1.foldLeft()((acc, e) => acc * e)
println(pro) //3628800
pro = ( /: l1)(_ * _)
println(pro) //3628800
排序
- 1.sortWith(p: (Int, Int) => Boolean)
val l1 = Range(, ).toList
var l2 = l1.sortWith((l, r) => l > r)
println(l2) //List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
l2 = l1.sortWith(_ > _)
println(l2) //List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)