可变容器与不可变容器
Scala虽然也提供了可变的(mutable)容器,但它更倾向于使用不变的(immutable)版本。不变容器不仅线程安全,而且没有副作用,有助于提升程序的正确性。在两个可供选择的包,只要在两个包选择一个即可:scala.collection.mutable或scala.collection.im-mutable。默认情况下,我们用的是
不可变Set和Map
。
Set
- 创建容器
val feeds1 = Set("blog.toolshed.com", "pragdave.pragprog.com", "pragmactic-osxer.blogspot.com", "vita-contemplativa.blogspot.com")
val feeds2 = Set("blog.toolshed.com", "martinfowler.com/bliki")
filter
过滤
val blogSpotFeeds = feeds1 filter ( _ contains "blogspot" )
+=()
添加
feeds1 += 'www.baidu.com'
++()
合并
val mergedFeeds = feeds1 ++ feeds2
size
元素个数
println("# of merged feeds: " + mergedFeeds.size)
**()
交集
val commonFeeds = feeds1 ** feeds2
map
处理每个元素,并返回结果集
val urls = feeds1 map ( "http://" + _ )
foreach
迭代处理每个元素
feeds1 foreach {
feed => println(" Refreshing " + feed )
}
toArray
复制到数组
println("One url: " + urls.toArray(0))
mkString
合并成字符串
println(feeds.mkString(','))
Map
- 创建容器
val feeds = Map("Andy Hunt" -> "blog.toolshed.com",
"Dave Thomas" -> "pragdave.pragprog.com",
"Dan Steinberg" -> "dimsumthinking.com/blog")
filterKeys()
按键过滤
val filterNameStartWithD = feeds filterKeys( _ startsWith "D" )
filter()
按键和值过滤
val filterNameStartWithDAndBlogInFeed = feeds filter { element =>
val (key, value) = element
(key startsWith "D") && (value contains "blog")
}
get()
取值
println("Get Andy's Feed: " + feeds.get("Andy Hunt"))
get()的返回类型是Option[T],结果可能是Some[T]或是None,其中T是Map里值的类型。
apply()
取值
try {
println("Get Andy's Feed Using apply(): " + feeds("Andy Hunt"))
print("Get Bill's Feed: ") println(feeds("Bill Who"))}
catch {
case ex : java.util.NoSuchElementException => println("Not found")
}
,apply()方法返回的不是Option[T],而是值。不同于get(),如果给定的键值没有对应的值,就会抛出异常。所以,请确保代码放到了一个try-catch块里
update
显式调用(添加元素)
val newFeeds1 = feeds.update("author", "blog")
若使用不变容器,update()并不会影响原来的Map。相反,它会返回一个新的Map,包含了新增的元素。
update
隐式调用
valnewFeed = feeds("author") = "blog" //等价于下式
valnewFeed = feeds.update("author", "blog")
如果对赋值左边的类或实例使用括号,Scala会自动调用update()方法。所以,X() = b等价于X.update(b)。如果update()的参数多于一个,可以将除了最后一个参数之外的所有参数放到括号里。所以,X(a) = b等价于X.update(a, b)。
- 可变Map
val mutableFeeds = scala.collection.mutable.Map("author" -> "bill")
mutableFeeds("title")= "learning java"
List
和Set和Map不同,List只有不变实现。
- 创建LIst
val feeds = List("blog.toolshed.com", "pragdave.pragprog.com", "dimsumthinking.com/blog")
- 访问List
println("First feed: " + feeds.head)
println("Second feed: " + feeds(1))
::()
添加元素(头部)
val prefixedList = "forums.pragprog.com/forums/87" :: feeds
:::()
连接List
val feedsWithForums = feeds ::: List("forums.pragprog.com/forums/87", "forums.pragprog. com/forums/55")
filter
过滤
println("Feeds with blog: " + feeds.filter( _ contains "blog" ). mkString(", "))
foreall
判断所有元素是否满足条件
feeds.forall( _ contains "com" ))
exists
判断是否存在元素满足条件
feeds.exists( _ contains "dave" ))
map
处理每个元素,并返回结果集
println("Feed url lengths: " + feeds.map( _.length ).mkString(", "))
foldLeft
val total = feeds.foldLeft(0) { (total, feed) => total + feed.length }
foldLeft()方法会从List的最左端开始为List的每个元素调用给定的函数值。函数值的第一个参数是
上一次函数值执行的结果
,第二个参数是List的元素。foldRight()做相同的事,不过是从右边开始。
foldLeft
的另一种调用/:
val total2 = (0 /: feeds) { (total, feed) => total + feed.length }
foldRight
的另一种调用: