Scala特性体验:集合/for表达式
Posted IT族装备党
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala特性体验:集合/for表达式相关的知识,希望对你有一定的参考价值。
package example
/**
* # Scala 有3种主要的集合类型
* List: 有序的对象集合
* Set: 无序的集合
* Map: 键值对字典
* 推崇使用不可变集合。
* Scala默认情况下,会使用不可变集合。
*/
//## Define Set
object SetTest extends App {
val colors1 = Set("Blue", "Green", "Red")
println(s"colors1: $colors1")
//colors1: Set(Blue, Green, Red)
var colors2 = colors1 + "Black" + "White"
println(s"colors2: $colors2")
println(s"colors1: $colors1")
//colors2: Set(Red, Blue, White, Black, Green)
//colors1: Set(Blue, Green, Red)
//(被默认包含的)Predef对象为Set与Map提供了别名,指向的是不可变的实现。
println(s"colors1 class=${colors1.getClass}")
//colors1 class=class scala.collection.immutable.Set$Set3
println(s"colors2 class=${colors2.getClass}")
//colors2 class=class scala.collection.immutable.HashSet$HashTrieSet
//Scala为大于4个元素的值创建HashSet的实现; 对于小于等于4个的Set,有专用实现。
}
//## Use Set
object SetUseTest extends App {
val feeds1 = Set("blog.toolshed.com", "pragdave.me", "blog.agiledeveloper.com")
val feeds2 = Set("blog.toolshed.com", "martinfowler.com/bliki")
//filter过滤符合条件的元素, mkString进行字符串Join拼接
val blogFeeds = feeds1 filter(_ contains "blog")
println(s"blog feeds: ${blogFeeds.mkString(", ")}")
//blog feeds: blog.toolshed.com, blog.agiledeveloper.com
//++() 合并两个集合并产生一个新集合
val mergeFeeds = feeds1 ++ feeds2
println(s"# of merged feeds: ${mergeFeeds.size}")
//# of merged feeds: 4
//&() 集合求交集
val commonFeeds = feeds1 & feeds2
println(s"common feeds: ${commonFeeds.mkString(", ")}")
//common feeds: blog.toolshed.com
//map() 一对一映射处理, head 取集合的第一个
val urls = feeds1 map ("http://" + _)
println(s"One url: ${urls.head}")
//One url: http://blog.toolshed.com
//foreach 遍历, 编写习惯: 需要明确lambda参数时使用{},否则使用()
println("Refresh Feeds:")
//占位符号_在这里无法使用
/**
* Error:(58, 43) error in interpolated string: identifier or block expected
* feeds1 foreach {println(s" Refreshing $_")}
* Error:(58, 46) ')' expected but '}' found.
* feeds1 foreach {println(s" Refreshing $_")}
*/
//feeds1 foreach {println(s" Refreshing $_")}
feeds1 foreach {f=>println(s" Refreshing $f")}
//Refresh Feeds:
// Refreshing blog.toolshed.com
// Refreshing pragdave.me
// Refreshing blog.agiledeveloper.com
}
//## Use Map
object MapUseTest extends App {
val feeds = Map(
"Andy Hunt" -> "blog.toolshed.com",
"Dave Thomas" -> "pragdave.me",
"NFJS" -> "nofluffjuststuff.com/blog"
)
//过滤出指定的Key
val filterNameStartWithA = feeds filterKeys( _ startsWith "A")
println(s"# of Filtered: ${filterNameStartWithA.size}")
//# of Filtered: 1
//过滤出指定的元组
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 pragdave in URL: 1
//使用get进行value的读取,返回的是个Option[T]
println(s"Get Andy's Feed: ${feeds.get("Andy Hunt")}")
//Get Andy's Feed: Some(blog.toolshed.com)
println(s"Get Bill's Feed: ${feeds.get("Bill Who")}")
//Get Bill's Feed: None
//直接使用apply()获取一个键的值
try{
println(s"Get Andy's Feed: ${feeds("Andy Hunt")}")
//Get Andy's Feed: blog.toolshed.com
print("Get Bill's Feed: ")
println(feeds("Bill Who"))
//Get Bill's Feed: Not found
}catch{
case _: java.util.NoSuchElementException => println("Not found")
/*
Exception in thread "main" java.util.NoSuchElementException: key not found: Bill Who
at scala.collection.immutable.Map$Map3.apply(Map.scala:242)
at example.MapUseTest$.delayedEndpoint$example$MapUseTest$1(SetTest.scala:101)
at example.MapUseTest$delayedInit$body.apply(SetTest.scala:73)
at scala.Function0.apply$mcV$sp(Function0.scala:39)
at scala.Function0.apply$mcV$sp$(Function0.scala:39)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
at scala.App.$anonfun$main$1$adapted(App.scala:80)
at scala.collection.immutable.List.foreach(List.scala:392)
at scala.App.main(App.scala:80)
at scala.App.main$(App.scala:78)
at example.MapUseTest$.main(SetTest.scala:73)
at example.MapUseTest.main(SetTest.scala)
*/
}
//向不可变map中添加元素时,将返回一个新map
val name = "Venkat Subramaniam"
val value="blog.agiledeveloper.com"
val newFeeds1 = feeds.updated(name, value)
println("Venkat's blog in original feeds: " + feeds.get(name))
//Venkat's blog in original feeds: None
println("Venkat's blog in new feeds: " + newFeeds1.get(name))
//Venkat's blog in new feeds: Some(blog.agiledeveloper.com)
//在scala 2.13.2 中测试,已经不支持 X(a)=b 等价于 X.updated(a,b) 这种模式了
//Error:(134, 17) value update is not a member of scala.collection.immutable.Map[String,String]
//val newFeed = feeds("author") = "blog"
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
}
/**
* FlatMap 会将多层Map打平为一层
*/
class People(val name: String, val friends: Seq[String]);
object UseFlatMap {
def main(args: Array[String]):Unit = {
// 创建2个人
val p1 = new People("小红", Seq("朋友1", "朋友2", "朋友3"));
val p2 = new People("小明", Seq("朋友3", "朋友4", "朋友5"));
// 加入到序列中
val seqs = Seq[People](p1, p2)
println("map的形式")
val c = seqs.map(f => f.friends)
println(c) //List(List(朋友1, 朋友2, 朋友3), List(朋友3, 朋友4, 朋友5))
/*
* 然而有些时候, 你并不希望得到这么一个需要访问两层才能拿到朋友对象的序列.
* 有时, 你希望得到的是一个在第一层就能访问到朋友的序列. 这就需要 flatMap:
*/
// flatMap
val d = seqs.flatMap(f => f.friends)
println("flatMap的形式")
println(d) //List(朋友1, 朋友2, 朋友3, 朋友3, 朋友4, 朋友5)
}
}
//## 使用不可变列表List
object UseListDemo extends App {
val feeds = List("blog.toolshed.com",
"pragdave.me",
"blog.agiledeveloper.com")
println(s"First feed: ${feeds.head}")
//First feed: blog.toolshed.com
println(s"Second feed: ${feeds(1)}")
//Second feed: pragdave.me
//a::list 将a前插到list
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
//将listA追加到另外一个列表list: list ::: listA
val feedsWithForums =
feeds ::: List(
"forums.prgprog.com/forums/87",
"forums.pragprog.com/forums/246"
)
println(s"First feed in feeds with forum: ${feedsWithForums.head}")
//First feed in feeds with forum: blog.toolshed.com
println(s"Last feed in feeds with forum: ${feedsWithForums.last}")
//Last feed in feeds with forum: forums.pragprog.com/forums/246
val appenedList = feeds ::: List("agilelearner.com")
println(s"Last feed in Appended: ${appenedList.last}")
//Last feed in Appended: agilelearner.com
println(s"Feeds with blog: ${feeds.filter(_ contains "blog").mkString(", ")}")
//Feeds with blog: blog.toolshed.com, blog.agiledeveloper.com
println(s"All feeds have com: ${feeds.forall(_ contains "com")}")
//All feeds have com: false
println(s"All feeds have dave: ${feeds.forall(_ contains "dave")}")
//All feeds have dave: false
println(s"Any feeds has dave: ${feeds.exists(_ contains "dave")}")
//Any feeds has dave: true
println(s"Any feeds has bill: ${feeds.exists(_ contains "bill")}")
//Any feeds has bill: false
println(s"Feed url lengths: ${feeds.map(_.length).mkString(", ")}")
//Feed url lengths: 17, 11, 23
//foldLeft方法将从列表的左侧开始,为列表中的每个元素调用给定的函值(代码块)
val total = feeds.foldLeft(0){(total, feed)=>total+feed.length}
println(s"Total length of feed urls: $total")
//Total length of feed urls: 51
}
//## for表达式
object UseForDemo extends App{
for( _ <- 1 to 3) { print("ho ")}
//"ho ho ho "
//一般的语法形式
/*
for([pattern <- generator; definitions*]+; filter*)
[yield] expression
*/
val result = for(i<- 1 to 10)
yield i * 2
println()
println(result)
//Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
val result2 = (1 to 10).map(_ * 2)
println(result2)
//Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
val tripEven = for ( i <- 1 to 10; if i%2 == 0)
yield i * 3
println(tripEven)
//Vector(6, 12, 18, 24, 30)
val tripEven2 = for {
i <- 1 to 10
if i%2 == 0
} yield i * 3
println(tripEven2)
//Vector(6, 12, 18, 24, 30)
class Person(val firstName: String, val lastName: String)
object Person {
def apply(firstName: String, lastName: String): Person =
new Person(firstName, lastName)
}
val firends = List(Person("Brian", "Sletten"),
Person("Neal", "Ford"),
Person("Scott", "Davis"),
Person("Stuart", "Halloway")
)//在新建一个Person的列表时实际上在幕后调用的是apply方法
//可以将定义与生成器放在一起,在每次迭代的过程中都会定义一个新的val值
val lastNames =
for( friend <- firends; lastName = friend.lastName) yield lastName
println(lastNames.mkString(", "))
//Sletten, Ford, Davis, Halloway
//在for表达式中提供了多个生成器,那么每个生成器都将形成一个内部循环, 最右边的生成器控制最里面的循环
for(i<- 1 to 3; j <- 4 to 6){
print(s"[$i,$j]")
}
println()
//[1,4][1,5][1,6][2,4][2,5][2,6][3,4][3,5][3,6]
}
以上是关于Scala特性体验:集合/for表达式的主要内容,如果未能解决你的问题,请参考以下文章