天天看點

scala築基篇-01-List操作List簡介建立清單操作

  • 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)
           

list對象的方法