Scala 集合

Table of Contents

1 数组(Array)

/*** 构造数组 ***/
val a = Array(1, 2, 3)
val a = new Array[Int](3) // 指定元素类型
// 还可以调用 Array 类的 apply 方法:
Array.apply(1, 2, 3)

/*** 访问数组 ***/
// 索引数组类似方法调用,索引从下标 0 开始。
var words = Array("a", "b", "c")
println(words(0)) // => a

/*** 更新数组元素 ***/
// 方法一,使用 update 方法:
a.update(0, 100)
// 方法二,直接按索引更新:
a(0) = 100

/*** 打印数组元素 ***/
println(Array(1, 2, 3))        // => [[email protected],默认无法打印全部元素
println(Array(1, 2, 3).deep) // => Array(1, 2, 3)
println(Array(1,2,3).mkString) // => 123

/*** 遍历数组 ***/
val words = Array("a", "b", "c")
// 方法1:
for (word <- words) println(word)
// 方法2:
words.foreach(println(_))
// 遍历时加入下标:
for ((i, word) <- words.zipWithIndex) println(i, word)

/*** Array 应用1:接受脚本参数 ***/
// 运行一个 Scala 脚本时,如果传递了参数,参数信息保存在 args 数组里,可以直接引用:
println(args(0))

2 列表(List)

/*** 构造列表 ***/
val = aList = List(1, 2, 3) // 其实等价于 List.apply(1, 2, 3)
val aList: List[Int] = List(1, 2, 3)
val aList: List[String] = List("1", "2", "3")
val aList: List[List[Int]] = List(List(1, 2, 3)) // 嵌套列表
// 构造空列表
val aList: List[Nothing] = Nil 或 val aList: List[Nothing] = List()
// 创建范围
val aList = List.range(1, 5) // => List(1, 2, 3, 4)
// 重复填充元素,注:老版本 Scala 用的 make 方法:List.make(5, 'a')
val aList = List.fill(5)('a') // => List(a, a, a, a, a)
List.fill(3, 2)('a') // => List(List(a, a), List(a, a), List(a, a))
// 还可用“::” cons 操作来构造列表(类似 Lisp):
// Nil 表示空列表,类似 Lisp 里的 nil。
1 :: 2 :: 3 :: Nil
// 用“:::”构造的列表就是平坦的:
List(1, 2) ::: List(3, 4) // res11: List[Int] = List(1, 2, 3, 4)

/*** 列表操作 ***/
// List 详细接口请见官方文档:http://www.scala-lang.org/api/2.11.5/index.html#scala.collection.immutable.List
// 列表 fold,其实就是 Reduce 操作,使用 =(start :/ List) (op)= 形式:
def sum(xs: List[Int]): Int = (0 /: xs) (_ + _)
sum(List(1, 2, 3)) // => 6
// 如果使用“\:”表示从左边开始 fold:
def sum(xs: List[Int]): Int = (xs :\ 0) (_ + _)
sum(List(1, 2, 3)) // => 6
// 上面代码表示 (1 + ( 2 + (3 + 0)))。

// tabulate,可以让每个元素都应用到一个函数:
List.tabulate(5)(_ * 10) // => res23: List[Int] = List(0, 10, 20, 30, 40)

// mkString,类似 Python 中的字符串 join 操作:
List(1, 2, 3).mkString(",") // => "1,2,3"

3 元组(Tuple)

// 类似 List,不同的是 Tuple 能包含不同类型元素,并且元素是固定不可变的。
/*** 构造 Tuple ***/
(1, 2, 3, "4")

/*** 访问 Tuple ***/
// Tuple 下标从 1 开始,而不是 0:
(1, 2, 3, "4")._1 // => res34: Int = 1

// 二元元组
("a" -> 1)

// 定义返回类型为元组的函数
def test() = ("a", "1") // => test: ()(String, String)
// 指定返回值类型:
def test(): (String, String) = ("a", "1") // => test: ()(String, String)

4 集合(Set)

// 集合包含不重复元素,也无顺序。

// 构造集合
Set(1, 2, 3, 3)

// 判断相等:
Set(1, 2, 3) == Set(1, 3, 2)

// 增加元素,使用“+”方法:
var aSet = Set(1, 2, 3, 3)
aSet += 4 // 由于 + 不会产生副作用,所以需要重新赋值

// 删除元素:
var aSet = Set(1, 2, 3)
aSet -= 3 // 如果不需要产生副作用,直接 aSet - 3 即可

// 交集
Set(1, 2, 3) & Set(1, 3, 5)

// 并集
Set(1, 2, 3) ++ Set(1, 3, 5)

// 补集
Set(1, 2, 3) -- Set(1, 3, 5)

5 映射(Map)

/* Map 特点:
- 映射的值甚至可以是函数
- 值不可变
- 键类型要一致
 */

// 创建 Map:
Map("a" -> 1, "b" -> 2)
// Map 的每个 key-value 对,都二元元组组成。

// 取值
Map("a" -> 1, "b" -> 2)("a") // => res43: Int = 1

// 增加元素:
x + ("c" -> 3) // 不会修改原对象,而是返回新的

// 删除元素:
x - "b"  // 不会修改原对象

6 可变集合

前面介绍的集合对象,都是不可修改的。

6.1 可变数组

import scala.collection.mutable.ArrayBuffer

val ab = ArrayBuffer[Int]() // => ab: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
ab += 1                     // => res0: ab.type = ArrayBuffer(1)
ab += 2                     // => res1: ab.type = ArrayBuffer(1, 2)
ab // => res2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2)

// 把 Array 类型转换成可变数组
val aBuffer = a.toBuffer
aBuffer += 1 // => res4: aBuffer.type = ArrayBuffer(1)
aBuffer // => res5: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1)

6.2 可变 List

import scala.collection.mutable.ListBuffer
val aList = ListBuffer[Int]() // => aList: scala.collection.mutable.ListBuffer[Int] = ListBuffer()
aList += 1                    // => res1: aList.type = ListBuffer(1)
aList += 2 // => res2: aList.type = ListBuffer(1, 2)
aList // => res3: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2)
aNewList.to[List // => List   ListBuffer
// List 类型转换成 ListBuffer 类型,互转方法相同
aNewList.to[ListBuffer] // => es4: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3)

6.3 可变 Map

import scala.collection.mutable.HashMap
val m = HashMap("a" -> 1) // => m: scala.collection.mutable.HashMap[String,Int] = Map(a -> 1)
m.update("b", 2)
m // => res2: scala.collection.mutable.HashMap[String,Int] = Map(b -> 2, a -> 1)

7 集合之间的转换

Array("a", "b", "c").toList // => List(a, b, c)
List("a", "b", "c").toArray // => [Ljava.lang.String;@6d311334
Array("a", "a", "a").toSet // => Set(a),也是一种去重的方法
List(("a", 1), ("b", 2)).toMap // => Map(a -> 1, b -> 2)

7.1 列表转 Map

// 列表元素必须是键值组合的结构才可以:
List(("a", 1), ("b", 2), ("c", 3)).toMap // => res2: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)

// 在不满足键值组合的情况下,先转换:
val aList = List("a", "b", "c") // => List: List[String] = List(a, b, c)
aList.map(_ -> true).toMap // => res1: scala.collection.immutable.Map[String,Boolean] = Map(a -> true, b -> true, c -> true)

7.2 将 Java 集合对象转成 Scala 集合对象

// 以 Java 的 HashMap 为例:
import java.util.HashMap
import scala.collection.JavaConverters._

val hashmap_for_java = new HashMap[String, Int]
hashmap_for_java.put("a", 1)
hashmap_for_java.put("b", 2)
hashmap_for_java.asScala // => res10: scala.collection.mutable.Map[String,Int] = Map(a -> 1, b -> 2)

8 组合子

// map
List(1, 2, 3, 4).map((i: Int) => i * 2)

// foreach,类似 map,但没有返回值,一般用在有副作用的。

// filter,过滤操作
// 如,移除返回为 false 的结果:
x.filter((i: Int) => i % 2 == 0)

// zip,两个列表聚合成一个聚偶列表

// partition,按谓词函数分割列表

// find,返回第一个被谓词函数匹配到的元素

// flatten,扁平化两个列表

// distinct,元素去重
List(1, 2, 2, 1).distinct // => res4: List[Int] = List(1, 2)