vlambda博客
学习文章列表

Scala特性体验:集合/for表达式

package example
/** * # Scala 有3种主要的集合类型 * List: 有序的对象集合 * Set: 无序的集合 * Map: 键值对字典 * 推崇使用不可变集合。 * Scala默认情况下,会使用不可变集合。 */
//## Define Setobject 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 Setobject 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 Mapobject 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) }}

//## 使用不可变列表Listobject 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]}