当前位置 博文首页 > 残缺的歌的专栏:scala List集合的用法

    残缺的歌的专栏:scala List集合的用法

    作者:[db:作者] 时间:2021-09-06 16:15

    一、前言:

    人们常说,Scala是一个难掌握的语言,一是其面向函数和面向对象结合的原因,二是其丰富的语法和内置函数。

    对于Conllection 这一章的内容,更多的是利用内置函数灵活地运用,避免自己重复造轮子(要求性能高除外)

    对于集合,通常来说有以下几个常用操作是必须掌握的:

    1.增删改查单个元素

    2.单个集合的各种遍历方式

    3.单个集合分拆组合与翻转

    4.两个集合的拼接,删除等操作

    ps(因为在官方文档中List是immutable的,所以对数组的所谓增上改查都是产生新的对象,并非在原来的集合上改动)

    A class for immutable linked lists representing ordered collections of elements of type.


    二、增删改查单个元素

    2-1 源码

    <span style="font-family: Arial, Helvetica, sans-serif;"></span><pre name="code" class="java">object ListBaseOps extends App {  
      
      /**
       * 1.增删改查单个元素
       */
      val list = List("scala","spark","hadoop")
      println("test"::list) // 增 (返回新对象,源对象不变)
      println(list(0))      //取
      println(list apply 0) //取  (同上) 
      // list(3) ="hadoop1";// 改  error (不能修改imutable的集合)
      println(list .updated(2,"hadoop1"))  //it works
      println(list.last)    //取最后一个元素 
      
    }  

     2-2 结果 
    

    List(test, scala, spark, hadoop)
    scala
    scala
    List(scala, spark, hadoop1)
    hadoop

    二、单个集合的各种遍历方式

    2-1例子

    object Test6 extends App() {
      /**
       * 单个集合的各种遍历方式
       */
       val lst = List(1,2,3,4,5);
       print("foreach遍历:")
       lst.foreach { x => print(x+",")}  //foreach遍历,这个是传统遍历,新手不熟无奈之下可以用它
       println("")
       
       var temp = lst.map { x => x+1 }   //遍历,与foreach的区别是返回值为List【B】
       println("map遍历:"+temp.mkString(","));
       
    
       var temp1 = lst.reduceLeft((sum,i)=>sum +i) //遍历,返回值类型是一个与集合相同的Int
        println("reduce遍历返回Int:"+temp1);
       
       var temp2 = lst.foldLeft(List[Int]())((x,y)=>y::x); //遍历,返回值是自定义类型
       //ps fold类函数还可以改成 :\ ,/:的形式,代码精简了不少,但是可读性却减低了例如
        println("foldLeft遍历返回自定义类型:"+temp2.mkString(","));
        
        var temp3=(   List[Int]() /: lst){(m,c)=>c::m} //遍历,实现反转
         println("foldLeft遍历实现反转:"+temp2.mkString(","));
      
    }
    2-1结果

    foreach遍历:1,2,3,4,5,
    map遍历:2,3,4,5,6
    reduce遍历返回Int:15
    foldLeft遍历返回自定义类型:5,4,3,2,1
    foldLeft遍历实现反转:5,4,3,2,1

    三、 单个集合分拆组合与翻转

    3-1源码例子

    object Test7 extends App() {
      /**
       * 单个集合的拆分组合与反转
       */
       val list = List(1,2,3,4,5);
      //除了最后一个元素之外的所有元素  (用法有点怪)
       println(list.init+"----init除了最后一个元素之外的所有元素")
      //除了第一个元素之外的所有元素  (用法有点怪)
       println(list.tail+"----tail除了第一个元素之外的所有元素")
       //生成迭代对象,注意区分init
       println(list.inits+"----inits生成迭代对象,注意区分init")
       
      val data = List('a','b','c','d','e')  
        //取前n个元素 
      var take = data take 2 
      println(take.mkString(",")+"-----take取前n个元素 ")  
      //除去前n个元素  
      var drop = data drop 2
      println(drop.mkString(",")+"-----drop除去前n个元素 ") 
      //返回元素的索引  
      println(data.indices+"----indices返回元素的索引  ")  
      //索引和数据组合长Tuple
      var t = data.indices zip data
      println(t.mkString +"----zip索引和数据组合长Tuple")  
      //数据和索引组合  
      println(data.zipWithIndex+"----zipWithIndex数据和索引组合")
       //grouped 分组 ?
    ? println(data.grouped(2).mkString(",")+"-----grouped分组");
    }
    3-2 结果
    List(1, 2, 3, 4)----init除了最后一个元素之外的所有元素
    List(2, 3, 4, 5)----tail除了第一个元素之外的所有元素
    non-empty iterator----inits生成迭代对象,注意区分init
    a,b-----take取前n个元素?
    c,d,e-----drop除去前n个元素?
    Range(0, 1, 2, 3, 4)----indices返回元素的索引 ?
    (0,a)(1,b)(2,c)(3,d)(4,e)----zip索引和数据组合长Tuple
    List((a,0), (b,1), (c,2), (d,3), (e,4))----zipWithIndex数据和索引组合
    List(a, b),List(c, d),List(e)-----grouped分组
    
    

    四、 两个集合的拼接,删除等操作

    4-1源码:

    object Test8 extends App() {
      /**
       * 集合间的链接交互
       */
      val left = List(1,2,3)
      val right = List(4,5,6)
    
      //以下操作等价
      println(left ++ right)   // List(1,2,3,4,5,6)
      println(left ++: right)  // List(1,2,3,4,5,6)
      println(right.++:(left))    // List(1,2,3,4,5,6)
      println(right.:::(left))  // List(1,2,3,4,5,6)
    
      //以下操作等价
      println(0 +: left)    //List(0,1,2,3)
      println(left.+:(0))   //List(0,1,2,3)
      //以下操作等价
      println(left :+ 4 )   //List(1,2,3,4)
      println(left.:+(4) )  //List(1,2,3,4)
      
      //以下操作等价
      println(0 :: left )     //List(0,1,2,3)
      println(left.::(0) )    //List(0,1,2,3)
       
    }
    4-2 总结:

    ++ ++[B](that: GenTraversableOnce[B]): List[B] 从列表的尾部添加另外一个列表

    ++: ++:[B >: A, That](that: collection.Traversable[B])(implicit bf: CanBuildFrom[List[A], B, That]): That 在列表的头部添加一个列表

    +: +:(elem: A): List[A] 在列表的头部添加一个元素

    :+ :+(elem: A): List[A] 在列表的尾部添加一个元素

    :: ::(x: A): List[A] 在列表的头部添加一个元素

    ::: :::(prefix: List[A]): List[A] 在列表的头部添加另外一个列表

    :\ :[B](z: B)(op: (A, B) ? B): B 与foldRight等价

    看到这里大家应该跟我一样有一点晕吧,怎么这么多奇怪的操作符,这里给大家一个提示,任何以冒号结果的操作符,都是右绑定的,即 0 :: List(1,2,3) = List(1,2,3).::(0) = List(0,1,2,3) 从这里可以看出操作::其实是右边List的操作符,而非左边Int类型的操作符





    cs