SCALA 集合框架文档翻译-Maps

Maps

英文原文:http://docs.scala-lang.org/overviews/collections/maps.html


        Map 是一个由键值对组成的可迭代(Iterable 类的实例)的集合(又称为映射或者关联)。Scala 的 Predef 类提供了一个隐示转换使得你可以用 key -> value 这样的语法来表示键值对 (key, value)。例如,Map("x"->24, "y"->25, "z"->26) 等同于 Map(("x", 24), ("y", 25), ("z", 26)),但是前者可读性更佳。

        Map 上的基本操作与 Set 上的类似。后面的表格中对它的基本操作进行了总结,其主要可以划分为几大类:

  • Lookup 类操作,apply、get、getOrElse、contains 以及 isDefinedAt。这些方法将 Map 集合转化为从键到值的偏函数。Map 基本的查找方法是:def get(key): Option[Value]。"m get key" 操作可以测试 Map 类集合中是否含有指定 key 的一个映射。如果包含,将以 Some 的形式返回该键对应的值,否则返回 None。Map 类集合还定义了 apply 方法,此方法直接返回 key 对应的值,而不是用 Option 类包裹起来再返回。如果指定 key 没有在 Map 中定义,则将会有异常抛出。
  • Additions and Updates 类操作,+、++ 以及 updated,用于添加新的键值对到 Map 中或者是更新已有键值对。
  • Removals 类操作,- 和 --,用于删除 Map 中的键值对。
  • Subcollection producers 类操作,keys、keySet、keysIterator、values 以及 valuesIterator,用于以不同的形式分别返回 Map 中的键或者值。
  • Transformations 类操作,filterKeys 和 mapValues,用于过滤 Map 中的元素以及转化 map 中的元素。
Map 类中的方法

方法作用
  
Lookups: 
ms get k以 Option 类包裹的方式返回 ms 中键 k 对应的值,如果不存在则返回 None
ms(k)(也可以写成 ms apply k)返回 ms 中键 k 对应的值,如果不存在则抛出异常
ms getOrElse (k, d)返回 ms 中键 k 对应的值,如果不存在则返回默认值 d
ms contains k判断 ms 中是否包含键 k 对应的一个映射对
ms isDefiniedAt k等同于 ms contains k
Additions and Update: 
ms + (k->v)返回一个新的 Map,包含原集合中所有元素以及给定 k->v 键值对
ms + (k->v, l->w)返回一个新的 Map,包含原集合中所有元素以及所有给定键值对
ms ++ kvs返回一个新的 Map,包含原集合中所有元素以及 kvs 中所有元素
ms updated (k, v)等同于 ms + (k->v)
Removals: 
ms - k返回一个新的 Map,包含原集合中除给定 k->v 键值对外的所有元素 
ms - (k, l, m)返回一个新的 Map,包含原集合中除所有给定键值对外的所有元素 
ms -- ks返回一个新的 Map,包含原集合中除 ks 中所包含的键对应的键值对外所有元素 
Subcollections: 
ms.keys返回一个包含 ms 中所有键的 Iterable 类集合
ms.keySet返回一个包含 ms 中所有键的 Set 类集合
ms.KeyIterator返回一个依次产生 ms 中键的迭代器
ms.values返回一个依次产生 ms 中键对应的值的 Iterable 类实例
ms.valuesIterator返回一个依次产生 ms 中键对应的值的迭代器
Transformations: 
ms filterKeys p返回 ms 中键满足谓词条件 p 的所有元素组成的一个新的 Map
ms mapValues f返回一个新的 Map,其中键与原集合相同,键对应的值为对原来值应用函数 f 的结果

可变 Map 在此基础上还添加了一些操作,总结如下表。

方法作用
  
Additons and Updates: 
ms(k) = v(也可以写成 ms.update(x, v))。
以副作用的方式添加从键 k 到值 v 的映射,
覆盖键 k 原来的值
ms += (k->v)以副作用的方式添加从键 k 到值 v 的映射,
如果原来存在,则覆盖键 k 原来的值
ms += (k->v, l->w)以副作用的方式添加给定键值对,
如果给定键原来存在,则覆盖该键对应的值
ms ++= kvs以副作用的方式添加 kvs 中所有键值对,
如果存在相同键则覆盖其对应的值
ms put (k, v)添加键值对 k->v 到 ms 中,
并以 Option 包裹的形式返回原来该键对应的值,
如果原来不存在该键则返回 None
ms getOrElseUpdate如果键 k 在 ms 中有定义,则返回其对应的值;
否则,用键值对 k->d 更新该键对应的值并返回新的值 d
Removals: 
ms -= k以副作用的方式从 ms 中删除给定键 k 对应的键值对,并返回 ms 本身
ms -= (k, l, m)以副作用的方式从 ms 中删除所有给定键对应的键值对,并返回 ms 本身
ms --= ks以副作用的方式从 ms 中删除集合 ks 中所包含的键对应的键值对,
并返回 ms 本身
ms remove k以副作用的方式从 ms 中删除给定键 k 对应的键值对,
并以 Option 包裹的方式返回键 k 对应的值,
如果原来就没有定键 k,则返回 None
ms retain p只保留 ms 中键满足谓词条件 p 的键值对,
以副作用的方式删除掉其他元素
ms.clear() 删除 ms 中所有的元素
Transformation: 
ms transform f返回一个新的 Map,其中键同原来集合,键对应的值为对键和值应用二元函数 f
Cloning: 
ms.clone返回一个新的 Map,元素同原来 Map

Map 的增加和删除操作与 Set 类似。如 Set 一样,可变的 Map 也提供了无副作用的增加、删除和更新操作:+、-、updated,但是这在可变集里面用的很少,因为这些操作涉及到重新拷贝一份 Map 数据。取而代之的是,可变 Map 总是使用 m(key) = value 和 m += (key->value) 这两个方法变体对集合进行“就地”更新。除了这两个方法,还有一个方法变体 m put (key, value),它除了添加给定键值对外,还返回一个用 Option 类包裹起来的原来键 key 对应的值,若原来键 key 不存在则返回 None。
        getOrElseUpdate 方法对作为缓存使用的 Map 的访问是非常有用的。比如说你定义了一个 计算开销很大的函数 f:

scala> def f(x: String) =  {
         println("taking my time."); sleep(100)
         x.reverse  }
f: (x: String) String

假设这里函数 f 没有副作用,则用相同的参数调用 f 总能返回相同的结果值。在这种情况下,你可以将参数和函数返回值作为键值对存储到一个 Map 缓存中,这样你就只用计算缓存中没有的参数。你可以认为这个 Map 是函数 f 计算的缓存。

scala> val cache = collection.mutable.Map[String, String]()
cache: scala.collection.mutable.Map[String, String] = Map()

你现在可以创建一个更高效的带缓存版本的函数 f:

def cachedF(arg: String) = cache get arg match {
    case Some(result) => result
    case None =>
        val result = f(x)
        cache(arg) = result
        result
 }

同步 Sets 和 Maps

你可以通过将 SynchronizedMap 特质混入到你使用的 Map 具体实现类上来获得一个线程安全的可变 Map。例如,可以将 SynchronizedMap 特质混入到 HashMap,如下面代码所示。这个例子开头导入了两个特质:Map 和 SynchronizedMap,一个包 scala.collection.mutable 中的类:HashMap。例子中的剩余部分定义了一个单例对象 MapMaker,其中定义了一个 makeMap 方法。这个 makeMap 方法声明了返回值类型为一个从 String 键到 String 值的可变 Map。

import scala.collection.mutable.{Map, SynchronizedMap, HashMap}

object MapMaker {
    def makeMap: Map[String, String] = {
        new HashMap[String, String] with SynchronizedMap[String, String] {
            override def default(key: String) = "Why do you want to know?"
        }
    }
}

makeMap 方法中的第一个语句构造了一个混入了 SynchronizedMap 特质的可变 HashMap:

new HashMap[String, String] with SynchronizedMap[String, String]

根据这行代码,scala 编译器将生成一个混入了 SynchronizedMap 特质的 HashMap 的子类,然后创建一个该生成类的实例并返回。这个混合类还重写了一个 default 方法,这可以根据以下代码得知:

override def default(key: String) = "Why do you want to know?"

如果你在一个 Map 中查询一个给定的 key,当这个 key 不存在的时候将会默认抛出一个 NoSuchElementException 异常。但是,如果你定义了一个 Map 并重写了它的 default 方法,则当你查询的 key 不存在的时候,将会返回 default 方法的返回值。因此,当你在以上同步 Map 的例子中去访问一个不存在的 key 的时候,这个编译器生成的 HashMap 的子类会返回一个简短的响应字符串“Why do you want to know?”。

        因为这个由 makeMap 方法返回的可变 Map 混入了 SynchronizedMap 特质,所以它可以同时被多个线程使用。对这个可变 Map 的访问是同步的。下面是一个解释器中运行的在一个线程中使用这个同步 Map 的例子:

scala> val capital = MapMaker.makeMap
capital: scala.collection.mutable.Map[String, String] = Map()
scala> capital ++ List("US" -> "Washington", "Paris" -> "France", "Japan" -> "Tokyo")
res0: scala.collection.mutable.Map[String, String] = Map(Paris -> France, US -> Washington, Japan -> Tokyo)
scala> captial("Japan")
res1: String = Tokyo
scala> capital("New Zealand")
res2: String = Why do you want to know?
scala> capital += (“New Zealand” -> "Wellington")
scala> capital("New Zealand")
res3: String = Wellington

你可以用类似的方法创建一个同步的 Set。例如,你可以创建一个同步的 HashSet,只要混入 SynchronizedSet 特质,就像下面这样:

import scala.collection.mutable
val synchroSet = new mutable.HashSet[Int] with mutable.SynchronizedSet[Int]

最后,如果你想使用同步集合,还可以考虑包 java.util.concurrent 中的同步集合类。










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值