目录
映射(Map)
定义
映射其实就是“键值对”,scala中分为:定长映射和变成映射。
定长映射:scala.collection.immutable.Map,使用时不需要引用
变成映射:scala.collection.mutable.Map,使用时需要引用,可以先创建一个空的映射对象scala.collection.mutable.HashMap
映射元素的表达形式分为两种,一种是“键 -> 值”的形式,另一种是“(键,值)”的形式,这里更推荐“键 -> 值”的形式,易读且与默认输出格式一致。
//定长映射的定义
scala> val map1 = Map("a" -> 1, "b" -> 2, "c" -> 3)
map1: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)
scala> val map2 = Map(("a",1), ("b" -> 2), ("c" -> 3))
map2: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)
//-------------------------------------------------
//变长映射的定义
scala> val map3 = new scala.collection.mutable.HashMap[String,Int]
map3: scala.collection.mutable.HashMap[String,Int] = Map()
scala> val map4 = scala.collection.mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)
map4: scala.collection.mutable.Map[String,Int] = Map(b -> 2, a -> 1, c -> 3)
scala> val map5 = scala.collection.mutable.Map(("a",1), ("b" -> 2), ("c" -> 3))
map5: scala.collection.mutable.Map[String,Int] = Map(b -> 2, a -> 1, c -> 3)
获取映射的值
scala中用“map("a")”的形式获取映射对应的值,类似java中“map.get("a")”。
如果获取不存在的键对应的值,胸将会报错“java.util.NoSuchElementException: key not found:”
可以通过contains方法判断键是否存在,返回Boolean类型。
由于在实际的使用过程中经常需要判断键是否存在,如果存在再取值,因此scala的映射类提供了getOrElse方法,判断键是否存在,如果不存在返回预设值。
scala> val map1 = Map("a" -> 1, "b" -> 2, "c" -> 3)
map1: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)
scala> map1("a") //类似java中map.get("a")
res0: Int = 1
scala> map1("d")
java.util.NoSuchElementException: key not found: d
at scala.collection.immutable.Map$Map3.apply(Map.scala:167)
... 28 elided
scala> map1.contains("a")
res2: Boolean = true
scala> map1.getOrElse("d",0) //判断d是否存在,如果不存在返回0
res4: Int = 0
修改、增加、删除映射
//定长映射
scala> val map1 = Map("a" -> 1, "b" -> 2, "c" -> 3)
map1: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)
//变长映射
scala> val map4 = scala.collection.mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)
map4: scala.collection.mutable.Map[String,Int] = Map(b -> 2, a -> 1, c -> 3)
//--------------------------------------------------------------
//修改映射
//修改定长映射的值会报错
scala> map1("a") = 10
<console>:13: error: value update is not a member of scala.collection.immutable.
Map[String,Int]
map1("a") = 10
^
scala> map4("a") = 10
scala> map4
res2: scala.collection.mutable.Map[String,Int] = Map(b -> 2, a -> 10, c -> 3)
//--------------------------------------------------------------
//增加映射
//定长映射再增加映射元素报错
scala> map1 += ("d" -> 4, "e" -> 5)
<console>:13: error: value += is not a member of scala.collection.immutable.Map[
String,Int]
Expression does not convert to assignment because receiver is not assignable.
map1 += ("d" -> 4, "e" -> 5)
^
scala> map4 += ("d" -> 4, "e" -> 5)
res4: map4.type = Map(e -> 5, b -> 2, d -> 4, a -> 10, c -> 3)
//--------------------------------------------------------------
//删除映射
//根据键删除映射元素
//定长映射会报错
scala> map1 -= "a"
<console>:13: error: value -= is not a member of scala.collection.immutable.Map[
String,Int]
Expression does not convert to assignment because receiver is not assignable.
map1 -= "a"
^
scala> map4 -= "a"
res7: map4.type = Map(e -> 5, b -> 2, d -> 4, c -> 3)
从上面可以看出,定长映射,除了能获取元素的值,其他啥操作都干不了。
映射的遍历
映射的遍历和java里的遍历很像
形如 “for((k,v) <- map) 处理k和v”的形式
scala> for((k,v) <- map1) println(k+" "+v)
a 1
b 2
c 3
还可以单独遍历key或者value
//单独遍历key,把可以转换成set集合并打印
scala> for(k <- map1.keySet) println(k)
a
b
c
//单独遍历value
scala> for(v <- map1.values) println(v)
1
2
3
//使用yield颠倒k,v
scala> val map2 = for((k,v) <- map1) yield (v,k)
map2: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b, 3 -> c)
元组(Tuple)
元组(tuple)是不同类型元素的聚集体,其实上面我们已经见到了元组
scala> val map = Map(("a",1),("b",2)) //("a",1)就是一个元组
map: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)
("a",1)就是一个元组
//大杂烩一般的tuple
scala> val a = (1,2.3,"34",true)
a: (Int, Double, String, Boolean) = (1,2.3,34,true)
scala> a._3
res6: String = 34
scala> a_3
<console>:12: error: not found: value a_3
a_3
^
scala> a _3
<console>:13: warning: postfix operator _3 should be enabled
by making the implicit value scala.language.postfixOps visible.
This can be achieved by adding the import clause 'import scala.language.postfixO
ps'
or by setting the compiler option -language:postfixOps.
See the Scaladoc for value scala.language.postfixOps for a discussion
why the feature should be explicitly enabled.
a _3
^
res8: String = 34
以“a._3”的形式访问元组中的元素,初始下标是1,这和数组不一样。也可以使用“a _3”访问元素,中间需要有a和_3中间有空格,但这种方式并不推荐。
一般一个方法或函数返回对个不同类型的值的时候,可以用tuple封装他们一起返回。这个很实用
拉链函数(zip)
把两个数组的元素平行绑定(下标0的元素绑定下标0的元素)形成一个元素为tuple的新的数组,如果拉链函数涉及到的两个数组元素个数不同,按照少的个数进行拉链操作。
scala> val a = Array("a","b","c")
a: Array[String] = Array(a, b, c)
scala> val b = Array(1,2,3)
b: Array[Int] = Array(1, 2, 3)
scala> val c = a.zip(b)
c: Array[(String, Int)] = Array((a,1), (b,2), (c,3))
//如果拉链函数涉及到的两个数组元素个数不同,按照少的个数进行拉链操作
scala> val c = a.zip(b)
c: Array[(String, Int)] = Array((a,1), (b,2), (c,3))
scala> val c = b.zip(a)
c: Array[(Int, String)] = Array((1,a), (2,b), (3,c))
拉链函数最后得到的是:Array((1,a), (2,b), (3,c)),元素的组成是不是很像Map元素的组成?我们可以使用toMap将这样的Array转换成Map。
scala> val map = b.zip(a).toMap
map: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b, 3 -> c)