快学Scala-第四章 映射和元组
知识点:
1.构造映射,映射是对偶的集合
val scores1 = Map("Alice" -> 10, "Bob" -> 7, "Cindy" -> 9) //不可变映射 // val scores1 = Map(("Alice",),("Bob",),("Cindy",)) val scores2 = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 7, "Cindy" -> 9) //可变映射 //构造一个空的映射 val scores3 = new scala.collection.mutable.HashMap[String,Int]
2.获取映射中的值
val bobscore = scores1("Bob") //如果不包含,则抛出异常 val bobscore1 = if(scores1.contains("Bob")) scores1("Bob") else 0 val bobscore2 = scores1.getOrElse("Bob", 0)
3.更新映射、迭代映射
在可变映射中,可以更新某个映射的值,或者添加一个新的映射关系,做法是在=号的左侧使用()
//可变映射 scores2("Bob") = 9 scores2("Fred") = 8 scores2 += ("Bob" -> 9, "Fred" -> 8) scores2 -= "Alice" //不可变映射 val newscores = scores1 + ("Bob" -> 9, "Fred" -> 8) //更新过的新映射,将结果作为新值保存 //更新var变量 var varscores = Map("Alice" -> 10, "Bob" -> 7, "Cindy" -> 9) varscores = varscores + ("Bob" -> 9, "Fred" -> 8) varscores = varscores - "Alice" //迭代映射 for((k,v) <- scores1) //处理k,v scores1.keySet //获得类似于 Set("a","b","c")这样的集合 for(v <- scores1.values) println(v) //values方法返回一个Iterable,可以在for循环中使用 for((k,v) <- scores1) yield (v,k) //反转一个映射
4.已排序映射
如下得到不可变的树型映射:
val scores4 = scala.collection.immutable.SortedMap("Alice" -> 10, "Bob" -> 7, "Cindy" -> 9)
对于可变的树型映射,最接近的选择是使用Java的TreeMap。
如果按插入顺序访问所有键,则使用LinkedHashMap。
val months = scala.collection.mutable.LinkedHashMap("January" -> 1,"February" -> 2,"March" -> 3,"April" -> 4, "May" -> 5,...)
5.与Java的互操作
将Java映射转换成一个Scala映射,以便使用更便捷的Scala映射API,这对于需要操作Scala并未提供的可变树形映射很有用。
import scala.collection.JavaConversions.mapAsScalaMap //指定Scala映射类型 val scores : scala.collection.mutable.Map[String,Int] = new java.util.TreeMap[String,Int] //java.util.Properties->Map[String,String] import scala.collection.JavaConversions.propertiesAsScalaMap val props : scala.collection.Map[String,String] = System.getProperties() //scala映射传递给预期的Java映射方法 import scala.collection.JavaConversions.mapAsJavaMap import java.awt.font.TextAttribute._ //引入下面的映射会用到的键 val attrs = Map(FAMILY -> "Serif", SIZE -> 12) //scala映射 val font = new java.awt.Font(attrs) //该方法预期一个Java映射
6.元组
映射是键/值对偶的集合,对偶是元组的最简单形态——元组是不同类型的值的聚集
元组的值是通过将单个的值包含在圆括号中构成的。使用_1 、_2 、_3访问其组元,元组的各组元从1开始。
val = (1,3.14,”Fred”)
val second = t._2 //second设为3.14
亦可 val second = t _2
7.拉链操作
val symbols = Array("<","-",">") val counts = Array(2,10,2) val pairs = symbols.zip(counts) pairs.toMap //拉链操作组合成一个映射
练习:(参考答案原网址)
1.设置一个映射,其中包含你想要的一些装备,以及它们的价格。然后构建另一个映射,采用同一组键,但是价格上打9折
scala> val price = Map("ipad" -> 4000,"iPhone" -> 6000, "iWatch" -> 3000) price: scala.collection.immutable.Map[String,Int] = Map(ipad -> 4000, iPhone -> 6000, iWatch -> 3000) scala> val newprice = for((k,v) <- price) yield (k, v * 0.9) newprice: scala.collection.immutable.Map[String,Double] = Map(ipad -> 3600.0, iP hone -> 5400.0, iWatch -> 2700.0)
2.编写一段程序,从文件中读取单词。用一个可变映射来清点每个单词出现的频率。读取这些单词的操作可以使用java.util.Scanner:
val in = new java.util.Scanner(new java.io.File("myfile.txt")) while(in.hasNext()) 处理 in.next() 或者翻到第9章看看更Scala的做法。 最后,打印出所有单词和它们出现的次数。
import scala.io.Source import scala.collection.mutable.HashMap object Pract { def main(args: Array[String]) = { val source = Source.fromFile("file.txt").mkString val tokens = source.split("\\s+") val map = new HashMap[String,Int] for(key <- tokens){ map(key) = map.getOrElse(key, 0) + 1 } println(map.mkString(",")) } }
3.重复前一个练习,这次用不可变的映射
不可变映射与可变映射的区别就是每次添加新的元素时都会返回一个新的映射。
import scala.io.Source object Pract { def main(args: Array[String]) = { val source = Source.fromFile("file.txt").mkString val tokens = source.split("\\s+") var map = Map[String,Int]() //注意这里用的 var 了 for(key <- tokens){ map += (key -> (map.getOrElse(key, 0) + 1)) } println(map.mkString(",")) } }
4.重复前一个练习,这次使用已排序的映射,以便单词可以按顺序打印出来
import scala.io.Source import scala.collection.SortedMap object Pract { def main(args: Array[String]) = { val source = Source.fromFile("file.txt").mkString val tokens = source.split("\\s+") var sortedmap = SortedMap[String,Int]() //注意这里用的 var 了 for(key <- tokens){ sortedmap += (key -> (sortedmap.getOrElse(key, 0) + 1)) } println(sortedmap.mkString(",")) } }
5.重复前一个练习,这次使用java.util.TreeMap并使之适用于Scala API
import scala.io.Source import scala.collection.mutable.Map import scala.collection.JavaConversions.mapAsScalaMap import java.util.TreeMap object Pract { def main(args: Array[String]) = { val source = Source.fromFile("file.txt").mkString val tokens = source.split("\\s+") val map:Map[String,Int] = new TreeMap[String,Int] for(key <- tokens){ map(key) = map.getOrElse(key, 0) + 1 } println(map.mkString(",")) } }
6.定义一个链式哈希映射,将"Monday"映射到java.util.Calendar.MONDAY,依次类推加入其他日期。展示元素是以插入的顺序被访问的
import scala.collection.mutable.LinkedHashMap import java.util.Calendar object Pract { def main(args: Array[String]) = { val map = new LinkedHashMap[String, Int] map += ("MONDAY" -> Calendar.MONDAY) map += ("TUESDAY" -> Calendar.TUESDAY) map += ("WENDSDAY" -> Calendar.WEDNESDAY) map += ("THURSDAY" -> Calendar.THURSDAY) map += ("FRIDAY" -> Calendar.FRIDAY) map += ("SATURDAY" -> Calendar.SATURDAY) map += ("SUNDAY" -> Calendar.SUNDAY) println(map.mkString(",")) } }
7.打印出所有Java系统属性的表格
JAVA系统属性转scala map的使用
import scala.collection.JavaConversions.propertiesAsScalaMap import scala.collection.Map object Pract { def main(args: Array[String]) = { val props: Map[String,String] = System.getProperties val keys = props.keySet val keylength = for( key <- keys) yield key.length val maxlength = keylength.max for( key <- keys) { print(key) print(" " * (maxlength - key.length)) print("| ") println(props(key)) } } }
8.编写一个函数minmax(values:Array[Int]),返回数组中最小值和最大值的对偶
def minmax(values:Array[Int]) = {
(values.max,values.min)
}
9.编写一个函数Iteqgt(values:Array[int],v:Int),返回数组中小于v,等于v和大于v的数量,要求三个值一起返回
def Iteqgt(values:Array[Int],v:Int) = { var a,b,c=0 for(value <- values){ if(value > v) a += 1 else if(value == v) b += 1 else c += 1 } (a,b,c) } def Iteqgt1(values:Array[Int],v:Int) = { (values.count(_ > v),values.count(_ == v), values.count(_ < v)) }
10.当你将两个字符串拉链在一起,比如"Hello".zip("World"),会是什么结果?想出一个讲得通的用例
scala> "Hello".zip("world") res0: scala.collection.immutable.IndexedSeq[(Char, Char)] = Vector((H,w), (e,o), (l,r), (l,l), (o,d))