对于scala中的.map()内部的循环:返回类型是"单位"

Bac*_*con 2 scala

编辑:我发现这是什么是斯卡拉的收益?(特别是第二个,最受欢迎的答案)在接受的答案解决了我的问题后非常有启发性.

==

我有一个HashMap,我想迭代它,并为每个键,使用for循环来创建新对象.

我正在尝试获取这些新对象的列表,但我总是给出一个空的"单元"序列.我想更好地理解我的代码的行为.

case class MyObject(one: String, two: String, three: Int)

val hm = new HashMap[String,Int]

hm += ("key" -> 3)
hm += ("key2" -> 4)

val newList = hm.map { case (key,value) =>
  for (i <- 0 until value) {
    new MyObject(key, "a string", i)
  }}.toSeq
Run Code Online (Sandbox Code Playgroud)

结果:

newList:Seq[Unit] = ArrayBuffer((), ())
Run Code Online (Sandbox Code Playgroud)

如果我不在.map()中使用任何for循环,我有我期望的结构类型:

val newList = hm.map { case (key,value) =>
    new MyObject(key, "a string", value)}.toSeq
Run Code Online (Sandbox Code Playgroud)

结果是:

 newList:Seq[MyObject] = ArrayBuffer(MyObject(key,host,3), MyObject(key2,host,4))
Run Code Online (Sandbox Code Playgroud)

cmb*_*ter 7

正如我在评论中提到的那样,你yieldmap陈述中缺少理解.如果你不包括yield关键字,那么你的理解纯粹是副作用而且不会产生任何结果.将其更改为:

for (i <- 0 until value) yield {
Run Code Online (Sandbox Code Playgroud)

现在从这里开始,你最终会得到一个Seq[IndexedSeq[MyObject]].如果你想最终得到一个Seq[MyObject]那么你可以flatten这样:

val newList = hm.map { case (key,value) =>
  for (i <- 0 until value) yield {
    MyObject(key, "a string", i)
  }}.toSeq.flatten
}
Run Code Online (Sandbox Code Playgroud)

而事实上(由@KarolS指出的),你甚至可以进一步通过更换缩短这个mapflatMap并删除明确的flatten结尾:

val newList = hm.flatMap { case (key,value) =>
  for (i <- 0 until value) yield {
    MyObject(key, "a string", i)
  }}.toSeq
}
Run Code Online (Sandbox Code Playgroud)