Scala List

来源:互联网 发布:石家庄seo顾问服务 编辑:程序博客网 时间:2024/05/22 13:21

Scala里List的设计
Scala List
Scala中Array和List的区别
Scala API文档——List

Scala中列表非常类似于数组,这意味着,一个列表的所有元素都具有相同的类型,但有两个重要的区别。首先,列表是不可变的,这意味着一个列表的元素可以不被分配来改变。第二,列表表示一个链表,而数组是平坦的。

// List of Stringsval fruit:List[String] = List("apples","oranges","pears")// List of Integersval nums:List[Int] = List(1,2,3,4)// Empty List:val empty:List[Nothing] = List()// Two dimensional listval dim: List[List[Int]] =     List(        List(1,0,0),        List(0,1,0),        List(0,0,1)    )

所有的列表可以使用两种基本的构建模块来定义,一个无尾Nil::,这有一个明显的缺点。Nil也代表了空列表。
所有上述列表可以定义如下:

//List of Stringsval fruit = "apples"::("oranges"::("pears"::Nil))//List of Integersval nums = 1::(2::(3::(4::Nil)))//Empty List.val empty = Nil//Two dimensional listval dim = (1::(0::(0::Nil)))::          (0::(1::(0::Nil)))::          (0::(0::(1::Nil)))::Nil
::的使用val a=List(12) //List[Int]=List[Int]val b=List('a') //List[Char]=List('a')val c=a::b      //List[AnyVal] = List(1,2,a)

列表的基本操作

方法 描述 head 此方法返回的列表中的第一个元素 tail 此方法返回一个由除了第一个元素外的所有元素的列表 isEmpty 如果列表为空,此方法返回true,否则为false
object  Test{    def main(args:Array[String]){    val fruit = "apples"::("oranges"::("pears"::Nil))    val nums = Nil    println("Head of fruit : " + fruit.head)  //apples    println("Tail of fruit : " + fruit.tail)  //List(oranges,pears)    println("Check if fruit is empty : " + fruit.isEmpty)  //false    println("Check if nums is empty : " + nums.isEmpty)  //true    }}

串联列表:::

可以使用:::运算符或列表List.:::()List.concat()方法来添加两个或多个列表。

object Test{    def main(args:Array[String]){    val fruit1 = "apples"::("oranges"::("pears"::Nil))    val fruit2 = "mangoes"::("banana"::Nil)    // use two or more lists with ::: operator    var fruit = fruit1 ::: fruit2    println("friut1 ::: friut2 : " + fruit)    //fruit1:::fruit2: List(apples, oranges, pears, mangoes, banana)    //use two lists with Set.:::() method    fruit = fruit1.:::(fruit2)    println("fruit1.:::(fruit2) : " + fruit)    //fruit1.:::(fruit2):List(mangoes, banana, apples, oranges, pears)    //pass two or more lists as arguments    fruit = List.concat(fruit1, fruit2)    println("List.concat(fruit1,fruit2): " + fruit)    }    //List.concat(fruit1,fruit2):List(apples,oranges,pears,mangoes,banana)}

创建同一列表List.fill()方法

可以用List.fill()方法创建,包括相同的元素如下的零个或更多个拷贝的列表:

object Test{    def main(args:Array[String]){        val fruit = List.fill(3)("appears") // Repeats apples three times        println("fruit:" + fruit)        // fruit: List(apples,apples,apples)        val num = List.fill(10)(2)        //Repeats 2,10 times.        println("num : " + num)        // num:List(2,2,2,2,2,2,2,2,2,2)    }}

tabulate 制成表格

object Test{    def main(args:Array[String]){        //Create 5 elements using the given function.        val squares = List.tabulate(6)(n=>n*n)        println("squares: " + squares)        //List(0,1,4,9,16,25)        //        val mul = List.tabulate(4,5)(_*_)        println("mul : " + mul)        //mul : List(List(0,0,0,0,0),List(0,1,2,3,4),                     List(0,2,4,6,8),List(0,3,6,9,12))    }}

反向列表顺序

object Test{    def main(args:Array[String]){    val fruit = "apples"::("oranges"::("pears"::Nil))    println("Before reverse fruit : " + fruit)    // Before reverse fruit: List(apples, oranges, pears)    println("After reverse fruit : " + fruit.reverse)    // After reverse fruit: List(pears, oranges, apples)}}

Scala 列表方法

  1. def ++[B](that:GenTraversableOnce[B]):List[B] 返回一个新List,包含左操作数,接着是右操作数中的元素,List的类型是两个操作数元素类型的超集。
  2. def ++:[B >: A, That](that: collection.Traversable[B])(implicit bf: CanBuildFrom[List[A],B,That]):That,和::不同的地方在于,右边操作数的类型决定了输出变量的类型。
  3. def +: (elem A):List[A],复制一个List,添加一个元素到List开头,原始列表不会被改变
  4. def /:[B](z:B)(op:(B,A)=>B):B,应用一个二元操作符给start value和所有可遍历的迭代器元素,从左到右. z /: xs == xs foldLeft z
  5. :+(elem A):List[A] : val a=List(1);val b = a:+2;//b:List[Int]=List(1,2)
  6. ::(x,A):List[A],在列表的开始添加一个元素。
  7. :::(prefix:List[A]):List[A],List(1,2):::List(3,4)=List(3,4).:::List(1,2)=List(1,2,3,4)
  8. def :\[B](z:B)(op:(A,B)=>B):B,xs :\ z == xs foldRight z
  9. def addString(b:StringBuilder):StringBuilder,把列表中的所有元素转成一个string builder,不同于toString.
  10. def addStirng(b:StringBuilder,sep:String),val a=List(1,2,3,4);val b = new StringBuilder();a.addString(b,",,")//StringBuilder = 1,,2,,3,,4
  11. def addString(b:StringBuilder, start:String, sep:String, end:String):StringBuilder,val a=List(1,2,3,4);val b=new StringBuilder();a.addString(b,"LIst(",",",")")//StringBuilder=List(1,2,3,4)
  12. def aggregate[B](z:=>B)(seqop:(B,A)=>B,combop:(B,B)=>B):B
  13. def andThen 函数组合相关
  14. def apply(n:Int):A,Select an element by its index in the sequence. Note, the execution of apply may take time proportional to the index value.(执行时间和index的大小成正比)
  15. applyOrElse[A1 <:Int, B1>:A](x:A1, default:(A1)=>B1):B1 偏函数
  16. canEqual(that:Any):Boolean
  17. ….还有茫茫多

List的链表结构

List是一个保证了前端入队和取尾集(tail)效率的不可变队列。
如:

val a = List(1,2,3)val b = 4::a

b=List(1,2,3,4).,在这个赋值过程中,没有发生对象复制,b的内部表示可以理解为是 4 -> List(1,2,3),也就是4->a.
其实,a的内部可以理解为 1->(2->(3->List())),这也解释了为什么List的元素访问复杂度是O(n).
List 与 Array (即使你不去改变Array内的元素)的主要区别是:
1. 它在API层面上保证了内部元素不变
2. 它取尾集(去掉头几个元素后剩下的List)的效率是很高的,非常适用基于模式匹配的迭代。
如:

def foo(I:List[Int])=>match I{    case x::xs => x + foo(xs)    case _=> 0}

如果用Array,每次递归都会导致n-1个元素被复制。如果在Java里,一般只能通过额外Index或Iterator来进行迭代。而index本身,就成了副作用,你必须关注某个动作应该在index变化之前还是之后做。

为什么列表不支持 append ?
类 List 没有提供 append 操作,因为随着列表变长 append 的耗时将呈线性增长,而使用 :: 做前缀则仅花费常量时间。如果你想通过添加元素来构造列表,你的选择是把它们前缀进去,当你完成之后再调用 reverse ;或使用 ListBuffer ,一种提供 append 操作的可变列表,当你完成之后调用 toList 。

0 0
原创粉丝点击