第8章——集合
Scala 标准库包含了一组丰富的集合类,以及用于组合、遍历和提取元素的强大操作。在 创建 Scala 应用程序时,会经常用到这些集合。如果想要在使用 Scala 时更加具有生产力,彻 底地学习这些集合是很有必要的。
8.1 常见的 Scala 集合
UsingCollections/UsingSet.scala
val colors1 = Set("Blue", "Green", "Red")
println(s"colors1: $colors1")
val colors2 = colors1 + "Black"
println(s"colors2: $colors2")
println(s"colors1: $colors1")
运行结果
colors1: Set(Blue, Green, Red)
colors2: Set(Blue, Green, Red, Black)
colors1: Set(Blue, Green, Red)
scala> val colors = Set("Blue", "Green", "Red")
colors: scala.collection.immutable.Set[String] = Set(Blue, Green, Red)
scala> colors.getClass
res0: Class[_ <: scala.collection.immutable.Set[String]] = class
scala.collection.immutable.Set$Set3
scala> :quit
8.2 使用 Set
UsingCollections/UsingSet.scala
val feeds1 = Set("blog.toolshed.com", "pragdave.me", "blog.agiledeveloper.com")
val feeds2 = Set("blog.toolshed.com", "martinfowler.com/bliki")
UsingCollections/UsingSet.scala
val blogFeeds = feeds1.filter(_ contains "blog")
println(s"blog feeds: ${blogFeeds.mkString(", ")}")
运行结果
blog feeds: blog.toolshed.com, blog.agiledeveloper.com
UsingCollections/UsingSet.scala
val mergedFeeds = feeds1 ++ feeds2
println(s"# of merged feeds: ${mergedFeeds.size}")
运行结果
# of merged feeds: 4
UsingCollections/UsingSet.scala
val commonFeeds = feeds1 & feeds2
println(s"common feeds: ${commonFeeds.mkString(", ")}")
运行结果
common feeds: blog.toolshed.com
UsingCollections/UsingSet.scala
val urls = feeds1.map("http://" + _)
println(s"One url: ${urls.head}")
运行结果
One url: http://blog.toolshed.com
UsingCollections/UsingSet.scala
println("Refresh Feeds:")
feeds1.foreach { feed =>
println(s" Refreshing $feed...")
}
运行结果
Refresh Feeds:
Refreshing blog.toolshed.com...
Refreshing pragdave.me...
Refreshing blog.agiledeveloper.com...
8.3 关联映射
UsingCollections/PlayingWithMap.scala
val feeds =
Map("Andy Hunt" -> "blog.toolshed.com", "Dave Thomas" -> "pragdave.me", "NFJS" -> "nofluffjuststuff.com/blog")
UsingCollections/PlayingWithMap.scala
val filterNameStartWithD = feeds.filterKeys(_.startsWith("D"))
println(s"# of Filtered: ${filterNameStartWithD.size}")
运行结果
# of Filtered: 1
UsingCollections/PlayingWithMap.scala
val filterNameStartWithDAndPragprogInFeed = feeds.filter { element =>
val (key, value) = element
(key.startsWith("D")) && (value contains "pragdave")
}
print("# of feeds with auth name D* and pragdave in URL: ")
println(filterNameStartWithDAndPragprogInFeed.size)
运行结果
# of feeds with auth name D* and pragprog in URL: 1
UsingCollections/PlayingWithMap.scala
println(s"Get Andy's Feed: ${feeds.get("Andy Hunt")}")
println(s"Get Bill's Feed: ${feeds.get("Bill Who")}")
运行结果
Get Andy's Feed: Some(blog.toolshed.com)
Get Bill's Feed: None
UsingCollections/PlayingWithMap.scala
try {
println(s"Get Andy's Feed Using apply(): ${feeds("Andy Hunt")}")
print("Get Bill's Feed: ")
println(feeds("Bill Who"))
} catch {
case _: java.util.NoSuchElementException => println("Not found")
}
运行结果
Get Andy's Feed Using apply(): blog.toolshed.com
Get Bill's Feed: Not found
UsingCollections/PlayingWithMap.scala
val newFeeds1 = feeds.updated("Venkat Subramaniam", "blog.agiledeveloper.com")
println("Venkat's blog in original feeds: " + feeds.get("Venkat Subramaniam"))
println("Venkat's blog in new feed: " + newFeeds1("Venkat Subramaniam"))
运行结果
Venkat's blog in original feeds: None
Venkat's blog in new feed: blog.agiledeveloper.com
UsingCollections/PlayingWithMap.scala
val mutableFeeds = scala.collection.mutable.Map("Scala Book Forum" -> "forums.pragprog.com/forums/87")
mutableFeeds("Groovy Book Forum") = "forums.pragprog.com/forums/246"
println(s"Number of forums: ${mutableFeeds.size}")
运行结果
Number of forums: 2
8.4 不可变列表
UsingCollections/PlayingWithList.scala
val feeds = List("blog.toolshed.com", "pragdave.me", "blog.agiledeveloper.com")
UsingCollections/PlayingWithList.scala
println(s"First feed: ${feeds.head}")
println(s"Second feed: ${feeds(1)}")
运行结果
First feed: blog.toolshed.com
Second feed: pragdave.me
UsingCollections/PlayingWithList.scala
val prefixedList = "forums.pragprog.com/forums/87" :: feeds
println(s"First Feed In Prefixed: ${prefixedList.head}")
运行结果
First Feed In Prefixed: forums.pragprog.com/forums/87
UsingCollections/PlayingWithList.scala
val feedsWithForums =
feeds ::: List("forums.pragprog.com/forums/87", "forums.pragprog.com/forums/246")
println(s"First feed in feeds with forum: ${feedsWithForums.head}")
println(s"Last feed in feeds with forum: ${feedsWithForums.last}")
运行结果
First feed in feeds with forum: blog.toolshed.com
Last feed in feeds with forum: forums.pragprog.com/forums/246
UsingCollections/PlayingWithList.scala
val appendedList = feeds ::: List("agilelearner.com")
println(s"Last Feed In Appended: ${appendedList.last}")
运行结果
Last Feed In Appended: agilelearner.com
UsingCollections/PlayingWithList.scala
println(s"Feeds with blog: ${feeds.filter(_ contains "blog").mkString(", ")}")
println(s"All feeds have com: ${feeds.forall(_ contains "com")}")
println(s"All feeds have dave: ${feeds.forall(_ contains "dave")}")
println(s"Any feed has dave: ${feeds.exists(_ contains "dave")}")
println(s"Any feed has bill: ${feeds.exists(_ contains "bill")}")
运行结果
Feeds with blog: blog.toolshed.com, blog.agiledeveloper.com
All feeds have com: false
All feeds have dave: false
Any feed has dave: true
Any feed has bill: false
UsingCollections/PlayingWithList.scala
println(s"Feed url lengths: ${feeds.map(_.length).mkString(", ")}")
运行结果
Feed url lengths: 17, 11, 23
UsingCollections/PlayingWithList.scala
val total = feeds.foldLeft(0) { (total, feed) =>
total + feed.length
}
println(s"Total length of feed urls: $total")
运行结果
Total length of feed urls: 51
UsingCollections/PlayingWithList.scala
val total2 = (0 /: feeds) { (total, feed) =>
total + feed.length
}
println(s"Total length of feed urls: $total2")
运行结果
Total length of feed urls: 51
UsingCollections/PlayingWithList.scala
val total3 = (0 /: feeds) { _ + _.length }
println(s"Total length of feed urls: $total3")
运行结果
Total length of feed urls: 51
8.5 方法名约定
UsingCollections/Colon.scala
class Cow {
def ^(moon: Moon): Unit = println("Cow jumped over the moon")
}
class Moon {
def ^:(cow: Cow): Unit = println("This cow jumped over the moon too")
}
UsingCollections/Colon.scala
val cow = new Cow
val moon = new Moon
cow ^ moon
cow ^: moon
运行结果
Cow jumped over the moon
This cow jumped over the moon too
UsingCollections/Unary.scala
class Sample {
def unary_+(): Unit = println("Called unary +")
def unary_-(): Unit = println("called unary -")
def unary_!(): Unit = println("called unary !")
def unary_~(): Unit = println("called unary ~")
}
val sample = new Sample
+sample
-sample
!sample
~sample
运行结果
Called unary +
called unary -
called unary !
called unary ~
8.6 for 表达式
UsingCollections/PowerOfFor.scala
for (_ <- 1 to 3) { print("ho ") }
UsingCollections/PowerOfFor.scala
val result =
for (i <- 1 to 10)
yield i * 2
UsingCollections/PowerOfFor.scala
val result2 = (1 to 10).map(_ * 2)
UsingCollections/PowerOfFor.scala
val doubleEven =
for (i <- 1 to 10; if i % 2 == 0)
yield i * 2
UsingCollections/PowerOfFor.scala
for {
i <- 1 to 10
if i % 2 == 0
} yield i * 2
UsingCollections/Friends.scala
class Person(val firstName: String, val lastName: String)
object Person {
def apply(firstName: String, lastName: String): Person =
new Person(firstName, lastName)
}
val friends =
List(Person("Brian", "Sletten"), Person("Neal", "Ford"), Person("Scott", "Davis"), Person("Stuart", "Halloway"))
val lastNames =
for (friend <- friends; lastName = friend.lastName) yield lastName
println(lastNames.mkString(", "))
运行结果
Sletten, Ford, Davis, Halloway
UsingCollections/MultipleLoop.scala
for (i <- 1 to 3; j <- 4 to 6) {
print(s"[$i,$j] ")
}
运行结果
[1,4] [1,5] [1,6] [2,4] [2,5] [2,6] [3,4] [3,5] [3,6]