scala列表
Scala的 list 类是不可变的, 大小及其中元素都不能修改, 它由链表实现.
List类是后进先出(LIFO), 类似栈访问模式的最好实现. 如果需要另外一种访问模式, 如FIFO可以考虑List之外的集合. List的前置, 头尾访问的时间复杂度都是o(1), 对于列表中的大多数的操作都是o(n)
创建与初始化
scala> val list = 1::2::3::Nil
list: List[Int] = List(1, 2, 3)
scala> val x = List(1,2.0,33D, 4000L)
x: List[Double] = List(1.0, 2.0, 33.0, 4000.0)
scala> val x = List(1,2.0,33D, 4000L)
x: List[Double] = List(1.0, 2.0, 33.0, 4000.0)
scala> val x = List.range(1,10)
x: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> val x = List.range(1,10,2)
x: List[Int] = List(1, 3, 5, 7, 9)
scala> val x = List.fill(5)("hello")
x: List[String] = List(hello, hello, hello, hello, hello)
scala> val x = List.tabulate(5)(n => n*n)
x: List[Int] = List(0, 1, 4, 9, 16)
scala> val x = collection.mutable.ListBuffer(1,2,3).toList
x: List[Int] = List(1, 2, 3)
scala> "hello".toList
res0: List[Char] = List(h, e, l, l, o)
List.tabulate() 方法是通过给定的函数来创建列表。 方法的第一个参数为元素的数量,可以是二维的,第二个参数为指定的函数起始值为 0
Nil是一个空的List,定义为List[Nothing],根据List的定义List[+A],所有Nil是所有List[T]的子类
:: 也叫做cons 方法接受两个参数:一个头元素,必须是单个元素,一个尾元素, 是另外一个List, 用这种方式去构造List,结尾必须是Nil元素Scala的List与java中的List类不同,如java的ArrayList, 所以一个java.util.List可以转化为Scaka Buffer或者seq, 而不是Scala List
创建可变List
List是不可变的,想使用可变列表 可以使用ListBuffer, 在必要时再将ListBuffer转换为List
如果创建要经常改变的列表,推荐在需要改变时使用ListBuffer, 需要时再转换为List
import scala.collection.mutable.ListBuffer
var fruits = new ListBuffer[String]()
//add one element at a time to the ListBuffer
fruits += "Apple"
fruits += "Banana"
fruits += "Orange"
//add multiple elements
fruits += ("Strawberry", "Kiwi", "Pineapple")
//remove one element
fruits -= "Apple"
//remove multiple element
fruits -=("Banana", "Orange")
//remove multiple elements specified by another sequence
fruits --= seq("kiwi", "Pineapple")
//convert the ListBuffer to a List when you need to
val fruitsList = fruits.toList
scaladoc指出一个ListBuffer是”一个基于列表的缓冲实现, 前置和附加操作的开销都是常量时间. 其他大多数的操作复杂度都是线性时间.” 因此, 想要通过索引的方式(如 list(1000)) 访问元素, 用ArrayBuffer,而不是ListBuffer
ListBuffer是一个可变的. 线性的序列(相对与索引序列,像一个数组或者ArrayBuffer),语法和java中的StringBuffer或者StringBuilder类似,就像是在需要时将这些类转换为String…
虽然不能修改List中的元素,但是可以用::方法将元素贴在列表的结尾,创建一个新的List
scala> val x = List(2)
x: List[Int] = List(2)
scala> val y = 1 :: x
y: List[Int] = List(1, 2)
scala> val z = 0::y
z: List[Int] = List(0, 1, 2)
添加/获取子集/删除
添加
val x = list(2)
val y = 1::x
val z = 0::y
添加时, 与其不断地将这个操作结果重新赋给一个新的变量, 不如将变量声明为var, 然后将结果重新赋给自己:
scala> var x = List(2)
x: List[Int] = List(2)
scala> x = 1::x
x: List[Int] = List(1, 2)
scala> x = 0::x
x: List[Int] = List(0, 1, 2)
:: 方法在列表前面添加元素,然后将结果赋给一个新的list
:: 是向右关联的, 列表都是从右向左构造而成的
scala> val a = 3::Nil
a: List[Int] = List(3)
scala> val a2 = 2::a
a2: List[Int] = List(2, 3)
scala> val a3= 3::a2
a3: List[Int] = List(3, 2, 3)
获取子集
通常使用filter, partition, splitAt, take等方法获取子集
删除
删除元素时可以使用可变序列的所有方法从中删除元素
import scala.collection.mutable.listBuffer
val x = listBUffer(1,2,3,4,5,6,7,8,9)
x -= 5
x -= (2, 3)
x.remove(0)
x.remove(1,3)
x --= seq(7,8,9)
合并连接
使用++ 、 concat 、 ::: 方法合并两个列表
scala> val a = 1::2::3::Nil
a: List[Int] = List(1, 2, 3)
scala> val b = 4::5::6::Nil
b: List[Int] = List(4, 5, 6)
scala> val c = a:::b
c: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> val d = a++b
d: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> val e = List.concat(a,b)
e: List[Int] = List(1, 2, 3, 4, 5, 6)
练习一:
object ListTest {
def main(args: Array[String]): Unit = {
val lst0 = List(1,8,2,3,6,4)
println("lst0 : "+lst0)
val lst1 = lst0.map { x => x*2 }
println("lst1 : "+lst1)
val lst2 = lst0.filter { x => x%2 == 0}
println("lst2 : "+lst2)
val lst3 = lst0.sorted
println("lst3 : "+lst3)
val lst4 = lst0.sortBy(x => -x)
println("lst4 : "+lst4)
val lst5 = lst0.sortWith((x,y)=> x<y )
println("lst5 : "+lst5)
val lst6 = lst0.reverse
println("lst6 : "+lst6)
//将lst0中的元素4个一组, 类型为Iterator[List[Int]]
val it = lst0.grouped(4)
for(x <- it){ println ("it "+x)}
//将Iterator转换成List
val lst7 = it.toList
//lst7: List[List[Int]] = List(List(1, 8, 2, 3), List(6, 4))
//将多个List压扁成一个List
val lst8 = lst7.flatten
//lst8: List[Int] = List(1, 8, 2, 3, 6, 4)
输出
lst0 : List(1, 8, 2, 3, 6, 4)
lst1 : List(2, 16, 4, 6, 12, 8)
lst2 : List(8, 2, 6, 4)
lst3 : List(1, 2, 3, 4, 6, 8)
lst4 : List(8, 6, 4, 3, 2, 1)
lst5 : List(1, 2, 3, 4, 6, 8)
lst6 : List(4, 6, 3, 2, 8, 1)
it List(1, 8, 2, 3)
it List(6, 4)
lst7 : List()
lst8 : List()
练习二:
scala> val a = Array ("a b c", "d e f", "h i j")
a: Array[String] = Array(a b c, d e f, h i j)
//先按空格切分, 再压平
scala> a.flatMap(_.split(" "))
res1: Array[String] = Array(a, b, c, d, e, f, h, i, j)
scala> var b = a.flatMap(_.split(" "))
b: Array[String] = Array(a, b, c, d, e, f, h, i, j)
scala> println(b(2))
c
scala> println(b)
[Ljava.lang.String;@6b8ef251
scala> print(b.toList)
List(a, b, c, d, e, f, h, i, j)
求和/乘
(reduce 实际调用的是reduceLeft => ((((1+8)+2))+3)+6)+4
1+8=9
9+2=11
11+3=14
…)
op:(A1,A1)=>A1
scala> val lst0 = List(1,8,2,3,6,4)
lst0: List[Int] = List(1, 8, 2, 3, 6, 4)
scala> lst0.reduce(_+_)
res5: Int = 24
scala> lst0.reduce(_*_)
res6: Int = 1152
reduce 实际调用 foldLeft
fold(初始值)
scala> val lst0 = List(1,8,2,3,6,4)
lst0: List[Int] = List(1, 8, 2, 3, 6, 4)
scala> 100+lst0.reduce(_+_)
res7: Int = 124
scala> lst0.fold(100)(_+_)
res8: Int = 124
scala> lst0.foldLeft(100)(_+_)
res9: Int = 124
scala> lst0.foldRight(100)(_+_)
res10: Int = 124
聚合
aggregate(0) 初始0
+.sum 子list内求和 (相当于map)
+ 所有子list求和(相当于reduce)
等同于:
aggregate(0)((x,y) => x + y.sum, (m,n) => m+n)
x=初始值0 (只加一次)
y.sum 子list和
m+n => ((list1.sum+list2.sum)+list3.sum)+list4.sum
scala> val arr = List(List(1,2,3), List(3,4,5), List(2), List(0))
arr: List[List[Int]] = List(List(1, 2, 3), List(3, 4, 5), List(2), List(0))
//每个子list内求和(相当于map过程), 然后所有子list求和(相当于reduce)
scala> val result = arr.aggregate(0)(_+_.sum, _+_)
result: Int = 20
并集, 交集, 差集
scala> val L1 = List(1,2,3,4)
L1: List[Int] = List(1, 2, 3, 4)
scala> val L2 = List(5,6,4,7)
L2: List[Int] = List(5, 6, 4, 7)
//求并集
scala> val r1 = L1.union(L2)
r1: List[Int] = List(1, 2, 3, 4, 5, 6, 4, 7)
//求交集
scala> val r2 = L1.intersect(L2)
r2: List[Int] = List(4)
//求差集
scala> val r3 = L1.diff(L2)
r3: List[Int] = List(1, 2, 3)
scala> println(r3)
List(1, 2, 3)
scala> val m = Map(("a",1))
m: scala.collection.immutable.Map[String,Int] = Map(a -> 1)
list并行求和
scala> lst0.par.sum
res14: Int = 24
scala> lst0.par.map(_%2 ==0)
res15: scala.collection.parallel.immutable.ParSeq[Boolean] = ParVector(false, true, true, false, true, true)
scala> lst0.par.reduce((x,y) => x+y)
res16: Int = 24