Scala是函数式风格与面向对象共存的编程语言,方法不该该有反作用是函数风格编程的一个重要的理念。方法惟一的效果应该是计算并返回值,用这种方式工做的好处就是方法之间不多纠缠在一块儿,所以就更加可靠和可重用。另外一个好处(静态类型语言)是传入传出方法的全部东西都被类型检查器检查,所以逻辑错误会更有可能把本身表现为类型错误。把这个函数式编程的哲学应用到对象世界里觉得着使对象不可变。
前面一章介绍的Array数组是一个全部对象都共享相同类型的可变序列。比方说Array[String]仅包含String。尽管实例化以后你没法改变Array的长度。所以,Array是可变的对象。
说到共享相同类型的不可变对象类型,Scala的List类才是。和数组同样,List[String]包含的仅仅是String。Scala的List不一样于Java的java.util.List,老是不可变的(Java的List是可变)。更准确的说法,Scala的List是设计给函数式风格的编程用的。前端
(1)List类型定义以及List的特色:java
//字符串类型List scala> val fruit=List("Apple","Banana","Orange") fruit: List[String] = List(Apple, Banana, Orange) //前一个语句与下面语句等同 scala> val fruit=List.apply("Apple","Banana","Orange") fruit: List[String] = List(Apple, Banana, Orange) //数值类型List scala> val nums=List(1,2,3,4,5) nums: List[Int] = List(1, 2, 3, 4, 5) //多重List,List的子元素为List scala> val list = List(List(1, 2, 3), List("adfa", "asdfa", "asdf")) list: List[List[Any]] = List(List(1, 2, 3), List(adfa, asdfa, asdf)) //遍历List scala> for(i <- list; from=i; j<-from)println(j) 1 2 3 adfa asdfa asdf
(2)List与Array的区别:es6
一、List一旦建立,已有元素的值不能改变,可使用添加元素或删除元素生成一个新的集合返回。
如前面的nums,改变其值的话,编译器就会报错。而Array就能够成功算法
scala>nums(3)=4 <console>:10: error: value update is not a member of List[Int] nums(3)=4 ^
二、List具备递归结构(Recursive Structure),例如链表结构
List类型和睦他类型集合同样,它具备协变性(Covariant),即对于类型S和T,若是S是T的子类型,则List[S]也是List[T]的子类型。
例如:编程
scala>var listStr:List[Object] = List("This", "Is", "Covariant", "Example") listStr:List[Object] = List(This, Is, Covariant, Example) //空的List,其类行为Nothing,Nothing在Scala的继承层次中的最底层 //,即Nothing是任何Scala其它类型如String,Object等的子类 scala> var listStr = List() listStr:List[Nothing] = List() scala>var listStr:List[String] = List() listStr:List[String] = List()
(3)List经常使用构造方法数组
//一、经常使用::及Nil进行列表构建 scala> val nums = 1 :: (2:: (3:: (4 :: Nil))) nums: List[Int] = List(1, 2, 3, 4) //因为::操做符的优先级是从右向左的,所以上一条语句等同于下面这条语句 scala> val nums = 1::2::3::4::Nil nums:List[Int] = List(1, 2, 3, 4) 至于::操做符的使用将在下面介绍
(4)List经常使用操做app
//判断是否为空 scala> nums.isEmpty res5: Boolean = false //取第一个元素 scala> nums.head res6: Int = 1 //取列表第二个元素 scala>nums.tail.head res7: Int = 2 //取第三个元素 scala>nums.tail.tail.head res8: Int = 3 //插入操做 //在第二个位置插入一个元素 scala>nums.head::(3::nums.tail) res11: List[Int] = List(1, 3, 2, 3, 4) scala> nums.head::(nums.tail.head::(4::nums.tail.tail)) res12: List[Int] = List(1, 2, 4, 3, 4) //插入排序算法实现 def isort(xs: List[Int]):List[Int] = { if(xs.isEmpty) Nil else insert(xs.head, issort(xs.tail)) } def insert(x:Int, xs:List[Int]):List[Int] = { if(xs.isEmpty || x <= xs.head) x::xs else xs.head :: insert(x, xs.tail) } //链接操做 scala>List(1, 2, 3):::List(4, 5, 6) res13: List[Int] = List(1, 2, 3, 4, 5, 6) //去除最后一个元素外的元素,返回的是列表 scala> nums.init res13: List[Int] = List(1, 2, 3) //取出列表最后一个元素 scala>nums.last res14: Int = 4 //列表元素倒置 scala> nums.reverse res15: List[Int] = List(4, 3, 2, 1) //一些好玩的方法调用 scala> nums.reverse.reverse == nums //丢弃前面n个元素 scala>nums drop 3 res16: List[Int] = List(4) //获取前面n个元素 scala>nums take 1 res17: List[Int] = List[1] //将列表进行分割 scala> nums.splitAt(2) res18: (List[Int], List[Int]) = (List(1, 2),List(3, 4)) //前一个操做与下列语句等同 scala> (nums.take(2),nums.drop(2)) res19: (List[Int], List[Int]) = (List(1, 2),List(3, 4)) //Zip操做 scala> val nums=List(1,2,3,4) nums: List[Int] = List(1, 2, 3, 4) scala> val chars=List('1','2','3','4') chars: List[Char] = List(1, 2, 3, 4) //返回的是List类型的元组(Tuple),返回的元素个数与最小的List集合的元素个数同样 scala> nums zip chars res20: List[(Int, Char)] = List((1,1), (2,2), (3,3), (4,4)) //List toString方法 scala> nums.toString res21: String = List(1, 2, 3, 4) //List mkString方法 scala> nums.mkString res22: String = 1234 //转换成数组 scala> nums.toArray res23: Array[Int] = Array(1, 2, 3, 4)
(5)List伴生对象方法xss
//apply方法 scala> List.apply(1, 2, 3) res24: List[Int] = List(1, 2, 3) //range方法,构建某一值范围内的List scala> List.range(2, 6) res25: List[Int] = List(2, 3, 4, 5) //步长为2 scala> List.range(2, 6,2) res26: List[Int] = List(2, 4) //步长为-1 scala> List.range(2, 6,-1) res27: List[Int] = List() scala> List.range(6,2 ,-1) res28: List[Int] = List(6, 5, 4, 3) //构建相同元素的List scala> List.make(5, "hey") res29: List[String] = List(hey, hey, hey, hey, hey) //unzip方法 scala> List.unzip(res20) res30: (List[Int], List[Char]) = (List(1, 2, 3, 4),List(1, 2, 3, 4)) //list.flatten,将列表平滑成第一个无素 scala> val xss = | List(List('a', 'b'), List('c'), List('d', 'e')) xss: List[List[Char]] = List(List(a, b), List(c), List(d, e)) scala> xss.flatten res31: List[Char] = List(a, b, c, d, e) //列表链接 scala> List.concat(List('a', 'b'), List('c')) res32: List[Char] = List(a , b, c)
(6)::和:::操做符介绍编程语言
List中经常使用'::',发音为"cons"。Cons把一个新元素组合到已有元素的最前端,而后返回结果List。函数式编程
scala> val twoThree = List(2, 3) scala> val oneTwoThree = 1 :: twoThree scala> oneTwoThree oneTwoThree: List[Int] = List(1, 2, 3)
上面表达式"1::twoThree"中,::是右操做数,列表twoThree的方法。可能会有疑惑。表达式怎么是右边参数的方法,这是Scala语言的一个例外的状况:若是一个方法操做符标注,如a * b,那么方法被左操做数调用,就像a.* (b)--除非方法名以冒号结尾。这种状况下,方法被右操做数调用。
List有个方法叫":::",用于实现叠加两个列表。
scala> val one = List('A', 'B') val one = List('A', 'B') scala> val two = List('C', 'D') scala> one:::two res1: List[Char] = List(A, B, C, D)
注意:
类List没有提供append操做,由于随着列表变长append的耗时将呈线性增加,而使用::作前缀则仅花费常量时间。若是你想经过添加元素来构造列表,你的选择是把它们前缀进去,当你完成以后再调用reverse;或使用ListBuffer,一种提供append操做的可变列表,当你完成以后调用toList。