您的位置:首页 > 其它

学习Scala——映射和元组

2017-12-14 18:06 417 查看
学习Scala——映射和元组

映射和和元组,也就是Maps和Tuples。Map这东西应该都挺明白的,就是键值对的集合。而元组,tuple,这东西并不是每个语言都有(Python中是有的,不过当时学的时候没有完全分清楚)。

在Scala中,元组是n个对象的一个聚集(Map是n=2个对象的聚集),里面的内容不需要都是相同类型的。

构造Map

在Scala中,Map是对偶(算是键值对的另一个说法吧)的集合。->操作符用来创建对偶, “Alice” -> 10产出 (“Alice”, 10)。

然后说说Scala中两个集合包的区别。在scala.collention.mutable包中的集合都是内容可变的,也就是创建了集合之后,集合的内容是可以变化的;而scala.collection.immutable包中,集合的内容是不可变的。由于拥抱函数式的缘故,默认都是使用immutable包。

// 创建一个内容不可变的Map[String, Int]

val scores = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)

// 创建一个内容可变的Map[String, Int]

val scores = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)

// 创建一个空Map[String, Int]

val scores = new scala.collection.mutable.Map[String, Int]

// 替换掉->操作符

val scores = Map(("Alice", 10), ("Bob", 3), ("Cindy", 8))

获取Map中的值

val bobsScore = scores("Bob")

如果Map中没有包含这个键值对,会抛出一个异常。用 contains()方法来检查是否包含指定的键。

val bobsScore = if (scores.contains("Bob")) scores("Bob") else 0

由于这个使用方法很多,所以有一个更加快捷的写法:

val bobsScore = scores.getOrElse("Bob", 0)

如果说像Java中,使用map.get(“Bob”),会如何?会返回一个Option对象,要么是Some,要么是None。关于Option,以后介绍…

更改Map

对于可变的Map,更改某个已有的值,或者是添加一个没有的对偶,都是如下:

scores("Fred") = 7

想要添加多个对偶,则使用+=操作:

scores += ("Bob" -> 10, "Fred" -> 7)

移除某个对偶使用-=:

scores -= "Alice"

对不可变的Map来说,操作基本都会是返回一个新的Map:

// 获取一个添加了新对偶的Map

val newScores = scores + ("Bob" -> 10, "Fred" -> 7)

// 获取一个移除了对偶的Map

val newScores = scores - "Alice"

不需要担心这种操作的效率会很低,新旧Map共享大部分的结构。

迭代Map

for ((k, v) <- map)

// 单独拿出键

for (k <- map.keySet)

// 单独拿出值

for (v <- map.values

已排序映射

在这里我知道了映射的实现方式通常是哈希表或者是一个平衡树。默认用的都是哈希表。如果需要一个排序的映射,就需要使用树形映射了。使用scala.collection.immutable.SortedMap即可。

不过Scala中并没有可变的树形映射,需要的时候使用Java中的TreeMap。

如果要按照插入的顺序访问所有键值,可以使用scala.collection.mutable.LinkedHashMap。

与Java的互操作

与数组中类似,引入函数后就可以触发转换。

// 从Java Map到Scala Map,适用于可变树形映射

import scala.collection.JavaConversions.mapAsScalaMap

// 从Java Properties到Scala Map

import scala.collection.JavaConversions.propertiesAsScalaMap

// 从Scala Map到Java Map

import scala.collection.JavaConversions.mapAsJavaMap

元组(Tuple)

元组是不同类型的值的聚集。

val t = (1, 3.14, "Fred") // 类型为Tuple3[Int, Double, java.lang.String]

// 访问组元

t._1 t._2 等方法,注意是从1开始的

// 不过通常是使用模式匹配来获取组元的

val (first, second, third) = t

// 如果说不是所有的组元都需要,那么在不需要的地方放上_

val (first, second, _) = t

有了这个,可以方便地返回多个值,让我想起了Go。

zip操作

看代码:

val symbols = Array("<", "-", ">")

val counts = Array(2, 10, 2)

val pairs = symbols.zip(counts)

// 得到:Array(("<", 2), ("-", 10), (">", 2))

// 可以使用toMap方法将对偶的集合转换成Map

keys.zip(values).toMap // 可想而知,这个集合需要是有序排列的

本章习题参考。

2.

import java.util.Scanner

import java.io.File

import scala.collection.mutable.HashMap

def tokenCount(file: File) = {

  val in = new Scanner(file)

  val map = new HashMap[String, Int]

  while (in.hasNext()) {

  val token = in.next()

    map(token) = map.getOrElse(token, 0) + 1

  }

  map

}

println(tokenCount(new File("piece.scala")).mkString(" ; "))

// 更加Scala的写法

import scala.io.Source

import scala.collection.mutable.HashMap

def tokenCount(fileName: String) = {

  val tokens = Source.fromFile(fileName).mkString.split("\\s+")

  val map = new HashMap[String, Int]

  for (token <- tokens) map(token) = map.getOrElse(token, 0) + 1

  map

}

println(tokenCount("piece.scala").mkString(" ; "))

3.

import scala.io.Source

import scala.collection.mutable.HashMap

def tokenCount(fileName: String) = {

  val tokens = Source.fromFile(fileName).mkString.split("\\s+")

  var map = new HashMap[String, Int]

  for (token <- tokens)

    map += (token -> (map.getOrElse(token, 0) + 1))

  map

}

println(tokenCount("piece.scala").mkString(" ; "))

5.

import scala.io.Source

import scala.collection.JavaConversions.mapAsScalaMap

import scala.collection.mutable.Map

def tokenCount(fileName: String) = {

  val tokens = Source.fromFile(fileName).mkString.split("\\s+")

  val map: Map[String, Int] = new java.util.TreeMap[String, Int]

  for (token <- tokens)

    map(token) = map.getOrElse(token, 0) + 1

  map

}

println(tokenCount("piece.scala").mkString(" ; "))

7.

import scala.collection.JavaConversions.propertiesAsScalaMap

def printJavaProperties() = {

  val properties: scala.collection.Map[String, String] = System.getProperties()

  val maxLength = properties.keySet.map(_.length).max

  for ((key, value) <- properties) {

    print(key)

    print(" " * (maxLength - key.length))

    print("|")

    println(value)

  }

}

printJavaProperties

原文链接:http://nerd-is.in/2013-08/learning-scala-maps-and-tuples/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: