Scala--映射和元祖

  映射,就是键值对偶的集合,元祖就是n个对象的聚集,所以对偶就是n=2的元祖。简单来说就相当于java中的Map。

定义

两种定义方式

1
2
3
4
5
6
7
8
9
scala> val map = Map("a" -> 1 , "b" -> 2 ,"c" -> 3)         ##第一种定义方式
map: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)

scala> map("d") = 4 ##赋值
<console>:12: error: value update is not a member of scala.collection.immutable.Map[String,Int]
map("d") = 4
^
scala> val map2 = Map(("a",1),("b",2),("c",3)) ##第二种定义方式
map2: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)

  1. 定义对偶:使用 “->“ 。
  2. 直接使用Map是使用immutable下面的Map,此时这个map是一个不可变的
  3. 如果要定义一个可变的Map需要scala.collection.mutable.Map,下面定义一个可变的map:
    1
    2
    3
    4
    5
    6
    7
    scala> val canchage = scala.collection.mutable.Map("a" -> 1 , "b" -> 2 ,"c" -> 3)
    canchage: scala.collection.mutable.Map[String,Int] = Map(b -> 2, a -> 1, c -> 3)

    scala> canchage("d") = 4 //能正常的修改值

    scala> canchage("d") //获取值
    res10: Int = 4

获取值

获取单个值

从上面的事例可以看出,获取值可以直接使用:变量名("key")

  • 但如果没有该key怎么办?
    1
    2
    3
    4
    5
    6
    7
    scala> map("d")
    java.util.NoSuchElementException: key not found: d
    at scala.collection.MapLike$class.default(MapLike.scala:228)
    at scala.collection.AbstractMap.default(Map.scala:59)
    at scala.collection.MapLike$class.apply(MapLike.scala:141)
    at scala.collection.AbstractMap.apply(Map.scala:59)
    ... 33 elided
  1. 当不存在key时,直接会抛出异常,可以使用contains进行判断;
  2. 或者直接使用,getOrElse("key",如不存在的值);
    1
    2
    3
    4
    5
    scala> map.contains("d")
    res14: Boolean = false

    scala> map.getOrElse("d",66)
    res15: Int = 66

迭代映射

for基础后,再来看迭代就很简单了,直接看事例吧:

  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    scala> for((k,v) <- map) print(k+"->"+v + ", ")     ##迭代键、值
    a->1, b->2, c->3,

    scala> for(k <- map.keySet) print(k+ ", ") ##迭代键
    a, b, c,

    scala> for(v <- map.values) print(v+ ", ") ##迭代值
    1, 2, 3,
  1. 基本语法就是:for((k ,v) <- 映射 ) 处理k/v
  2. 如果只想获取值就迭代values,只想获取键迭代keySet

更新值

  • 下面更新操作都是在可变的映射下完成,现在canchage中有key->a、b、c、d
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> canchage("d") = 7                            ##直接修改
    scala> canchage("e") = 5 ##不存在该值即添加该元祖
    scala> canchage ##查看一下map中的数据
    res23: scala.collection.mutable.Map[String,Int]=Map(e->5,b->2,d->7,a->1,c->3)
    scala> canchage += ("e"-> 1 ,"f"->6) ##这样同样可以修改和增加
    res24: canchage.type = Map(e -> 1, b -> 2, d -> 7, a -> 1, c -> 3, f -> 6)

    scala> canchage -= ("e","a") ##删除多个
    res25: canchage.type = Map(b -> 2, d -> 7, c -> 3, f -> 6)
    scala> canchage -= "b" ##删除单个
    res26: canchage.type = Map(d -> 7, c -> 3, f -> 6)
  1. 从上面的事例可以看出map的顺序在不断地改变,如果要创建一个不可变的Map使用:scala.collection.mutable.LinkedHashMap

  2. 对于不可变的映射,可以重新再定义一个变量,后面添加需要修改和添加的值。

    1
    2
    3
    4
    5
    6

    scala> map
    res43: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)

    scala> val mapch = map + ("a"->10 , "d"->14) ##mapch同样不可改变
    mapch: scala.collection.immutable.Map[String,Int] = Map(a -> 10, b -> 2, c -> 3, d -> 14)

与java互转

示例代码,java 转为scala

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import scala.collection.JavaConverters;
import scala.collection.immutable.Map$;

import java.util.HashMap;
import java.util.Map;

/**
* java 代码
* javamap 转为scala map
* Created by xiaoxiaomo on 2016/3/26.
*/
public class JavaMap {

public static void main(String[] args) {

// 获取一个java Map
Map<String, Integer> map = getJavaMap();

//java map 转换为可变的scala map
scala.collection.mutable.Map<String, Integer> mutableMap = JavaConverters.mapAsScalaMapConverter(map).asScala();
System.out.println(mutableMap.keySet());

//java map 转换为不可变的scala map
Object obj = Map$.MODULE$.<String,Integer>newBuilder().$plus$plus$eq(mutableMap.toSeq());
Object result = ((scala.collection.mutable.Builder) obj).result();

scala.collection.immutable.Map<String,String> immutableMap = (scala.collection.immutable.Map)result;
System.out.println(immutableMap.keySet());
}

public static Map<String,Integer> getJavaMap(){
Map<String,Integer> map = new HashMap<String,Integer>() ;
map.put("a",1);
map.put("b", 2);
return map ;
}

}

元祖

元祖,就是不同类型值的聚集。元祖的值是通过将单个的值包含在圆括号中构成的。下面来看看元祖的一些使用(赋值、获取值)。

  • 实例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    scala> ("blog",".","xiaoxiaomo",19)
    res31: (String, String, String, Int) = (blog,.,xiaoxiaomo,19)

    scala> res31._1 ##可以看出元祖的下标是从1开始,获取值使用“._”
    res32: String = blog

    scala> res31 _3 ##第二种获取元祖方法“ _”,注意中间有一个空格
    warning: there was one feature warning; re-run with -feature for details
    res33: String = xiaoxiaomo
  • 还有另一种获取元祖的方式,叫做模式匹配。这种方式可使一个方法变相的返回多个返回值,示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    scala> val (a,b,c,_) = res31 ##hexo不想匹配的值使用“_”
    a: String = blog
    b: String = .
    c: String = xiaoxiaomo

    scala> a
    res34: String = blog

    scala> c
    res35: String = xiaoxiaomo

拉链操作

元祖可以把很多值关联起来,以便统一处理。对于这种链式处理,我们还可以使用zip,还可以让两个数组组合成一个对偶数组,然后对偶数组可以toMap转为映射。

  • 示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> var k = Array("a","b","c")       ##数组1
    k: Array[String] = Array(a, b, c)

    scala> var v1 = Array(7,8,9) ##数组2
    v1: Array[Int] = Array(7, 8, 9)

    scala> k.zip(v1) ##两个数组组合成一个对偶数组
    res37: Array[(String, Int)] = Array((a,7), (b,8), (c,9))

    scala> res37.toMap ##对偶数组转为映射
    res38: scala.collection.immutable.Map[String,Int] = Map(a -> 7, b -> 8, c -> 9)
  • :如果两个数组的长度不一致,会以长度短的为准,长的数据会丢失。

    1
    2
    3
    4
    5
    6
    7
    8
    scala> var v = Array(7,8,9,10)
    v: Array[Int] = Array(7, 8, 9, 10)

    scala> k.zip(v)
    res39: Array[(String, Int)] = Array((a,7), (b,8), (c,9))

    scala> v.zip(k)
    res41: Array[(Int, String)] = Array((7,a), (8,b), (9,c))

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器