美文网首页scala-筑基篇
scala-筑基篇-01-List操作

scala-筑基篇-01-List操作

作者: hylexus | 来源:发表于2016-10-06 03:32 被阅读108次

    [TOC]

    List简介

    特性

    • 不可变
    • 递归结构
    • 同构(同质)的:元素的类型必须一致
    • 协变的:如果S是T的子类型,那么List[S]是List[T]的子类型,这点不同于java的泛型
    • 空列表为List[Nothing],Nil

    创建列表

    • 所有的List都是由空列表Nil和操作符::构造出来的,::表示从前端扩张列表.
    • 实际上,用形如List(e1,e2,...)的方式创建列表在底层也是使用Nil::构造出来的
    scala> List(1,2,3)
    res0: List[Int] = List(1, 2, 3)
    
    scala> 1::Nil
    res1: List[Int] = List(1)
    
    scala> 2::res1
    res2: List[Int] = List(2, 1)
    
    scala> 3::res2
    res3: List[Int] = List(3, 2, 1)
    

    操作

    list的基本操作

    method DESC
    head List的第一个元素
    tail 除了head之外的其他元素组成的List
    isEmpty List是否为空
    last List的最后一个元素
    init 除了last之外的其他元素组成的List
    scala> val l1=List(1,2,3,4,5)
    l1: List[Int] = List(1, 2, 3, 4, 5)
    
    scala> l1.tail
    res4: List[Int] = List(2, 3, 4, 5)
    
    scala> l1.head
    res5: Int = 1
    
    scala> l1.isEmpty
    res6: Boolean = false
    
    scala> l1.init
    res7: List[Int] = List(1, 2, 3, 4)
    
    scala> l1.last
    res8: Int = 5
    

    list类的一阶方法

    连接

    列表的链接操作符:::和扩展元素操作符::一样都是右结合的,即xs:::ys:::zs等价于xs:::(ys:::zs),不过两个操作数都是List

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

    长度

    内部定义:

      def length: Int = {
        var these = self
        var len = 0
        while (!these.isEmpty) {
          len += 1
          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(1,11).toList
    l1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    
    scala> l1.take(3)
    res10: List[Int] = List(1, 2, 3)
    
    scala> l1.drop(3)
    res11: List[Int] = List(4, 5, 6, 7, 8, 9, 10)
    
    scala> l1.splitAt(3)
    res12: (List[Int], List[Int]) = (List(1, 2, 3),List(4, 5, 6, 7, 8, 9, 10))
    

    apply | indices

    scala> val l1=Range(1,11).toList
    l1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    
    scala> l1.apply(2)
    res13: Int = 3
    
    scala> l1(2)
    res14: Int = 3
    
    scala> l1.indices
    res15: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    

    zip

    不匹配的元素将被遗弃

    scala> val l1=Range(1,4).toList
    l1: List[Int] = List(1, 2, 3)
    
    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((1,a), (2,b), (3,c))
    

    mkString

    mkString([start,]seperator[,end])

    scala> val l=Range(1,5).toList
    l: List[Int] = List(1, 2, 3, 4)
    
    scala> l.mkString("start","|","end")
    res17: String = start1|2|3|4end
    
    scala> l.mkString("|")
    res18: String = 1|2|3|4
    

    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(1, 11).toList
    l1.foreach(e => { print(e + " ") })
    
    l1.foreach(print(_))
    

    等价的java8操作

    List<Integer> list = Stream.iterate(1, i -> i + 1).limit(10)
            .collect(Collectors.toList());
    list.forEach(e -> {
        System.out.print(e + " ");
    });
    
    list.forEach(System.out::print);
    

    求和

    val l1 = Range(1, 11).toList
    var sum = 0
    l1.foreach(sum += _)
    println(sum)
    

    map

    参数f:T=>R,将f作用于每个元素,并返回类型为R的新列表

    构造新list,元素为原list的元素的2倍

    l1.map(e => e * 2)
    println(l1)
    

    等价的java8代码

    list.stream().map(e->e*2).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(1,11).toList
    l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    
    scala> l.filter(e=>(e%2)==0)
    res22: List[Int] = List(2, 4, 6, 8, 10)
    
    scala> l.filter(e=>(e&1)==0)
    res24: List[Int] = List(2, 4, 6, 8, 10)
    

    partition

    返回二元组(符合条件的部分,不符合条件的部分)

    scala> val l=Range(1,11).toList
    l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    
    scala> l.partition(e=>(e%2)==0)
    res26: (List[Int], List[Int]) = (List(2, 4, 6, 8, 10),List(1, 3, 5, 7, 9))
    

    find

    返回第一个满足条件的

    scala> l.find(e=>(e%2)==0)
    res27: Option[Int] = Some(2)
    

    takeWhile | dropWhile | span

    • takeWhile(p):返回能够满足p的最长前缀组成的list
    • dropWhile(p):返回list中除了takeWhile(n)的部分组成的列表
    • span:类似于slitAt结合了take和drop,span结合了takeWhile和dropWhile的结果
    scala> val l=List(1,2,3,-1,2,3)
    l: List[Int] = List(1, 2, 3, -1, 2, 3)
    
    scala> l.dropWhile(_>0)
    res28: List[Int] = List(-1, 2, 3)
    
    scala> l.takeWhile(_>0)
    res30: List[Int] = List(1, 2, 3)
    
    scala> l.span(_>0)
    res31: (List[Int], List[Int]) = (List(1, 2, 3),List(-1, 2, 3))
    

    论断(forall,exists)

    scala> val l=List(1,2,3,-1,2,3)
    l: List[Int] = List(1, 2, 3, -1, 2, 3)
    
    scala> l.forall(_>0)
    res33: Boolean = false
    
    scala> l.exists(_>0)
    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(1, 11).toList
    
    var sum = l1.foldLeft(0)((acc, e) => acc + e)
    println(sum) //55
    
    sum = l1./:(0)((acc, e) => acc + e)
    println(sum) //55
    
    sum = l1.foldRight(0)((e, acc) => acc + e)
    println(sum) //55
    
    sum = l1.fold(0)((acc, e) => acc + e)
    println(sum) //55
    
    sum = l1.foldLeft(0)(_ + _)
    println(sum) //55
    
    sum = l1./:(0)(_ + _)
    println(sum) //55
    
    sum = (0 /: l1)(_ + _) //相当于 l1./:(0)
    //sum = (l1 /: 0)(_ + _) //错误,相当于0./:(l1)
    println(sum) //55
    

    乘积

    var pro = 1
    val l1 = Range(1, 11).toList
    pro = l1.foldLeft(1)((acc, e) => acc * e)
    println(pro) //3628800
    
    pro = (1 /: l1)(_ * _)
    println(pro) //3628800
    

    排序

    • 1.sortWith(p: (Int, Int) => Boolean)
    val l1 = Range(1, 11).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对象的方法

    相关文章

      网友评论

        本文标题:scala-筑基篇-01-List操作

        本文链接:https://www.haomeiwen.com/subject/qmdeyttx.html