使用for/yield组合创建新集合

在Scala的for表达式中,可以使用yield关键字来生成新的集合:

val nieces = Array("java", "python", "scala", "php")
for (n <- nieces) yield n.capitalize

// 使用 for/yield 创建新数组
var temp = for (i <- Array(1, 5, 3, 7)) yield i * 2
println(temp.toBuffer)

输出结果如下:

nieces: Array[String] = Array(java, python, scala, php) 
res113: Array[String] = Array(Java, Python, Scala, Php)

yield的主要作用是记住每次迭代中的有关值,并逐一存入到一个集合中, 循环结束后将返回该集合。其语法如下:

for {子句} yield {变量或表达式}。

例如,下面两句是等价的:

// 遍历集合,返回一个新的集合
val newArray1 = for (e <- nieces) yield e.toUpperCase

// 等价于上一句
val newArray2 = for (e <- nieces) yield {
    val s = e.toUpperCase
    s
}

输出结果如下:

newArray1: Array[String] = Array(JAVA, PYTHON, SCALA, PHP) 
newArray2: Array[String] = Array(JAVA, PYTHON, SCALA, PHP)

var a = 0;
val numList = List(1,2,3,4,5,6,7,8,9,10);

// for 循环
var retVal = for( a <- numList 
                  if a != 3; if a < 8
                ) yield a

// 输出返回值
for( a <- retVal){
    println( "a = " + a );
}

从一个已经存在的集合根据一定的算法生成一个新的集合:

// 给定一个数组
val names2 = Array("chris", "ed", "maurice")
val capNames = for (e <- names2) yield e.capitalize

// 算法可能有多行
val lengths = for (e <- names2) yield {
   // 多行代码
   e.length
}
    
val fruits = "apple" :: "banana" :: "orange" :: Nil
val out = for (e <- fruits) yield e.toUpperCase

// 调用map方法完成同样的事
val out3 = fruits.map(_.toUpperCase)

yield关键字的简短总结:

  • 针对每一次for循环的迭代,yield会产生一个值,被循环记录下来;
  • 当循环结束后, 会返回所有yield的值组成的集合;
  • 返回集合的类型与被遍历的集合类型是一致的。

《Flink原理深入与编程实战》