Scala中的foreach和map有什么区别?

5
我尝试了两种方法将某些内容制作成列表
var response = List[RS_TxnNested]
consumertxnlist.foreach(txData => {
  response = RS_TxnNested(blabla) +: response
})

consumertxnlist是一个Seq[something]。

另一种方式是

var response = consumerTxnList._2.map(txData => RS_TxnNested(blabla))

有人能帮我澄清哪个更好,为什么更好吗?


我认为你可以在这里找到答案:https://dev59.com/H2Qn5IYBdhLWcg3wIUJn。 - Sandeep Purohit
5个回答

12

正如您已经注意到的那样,Seq trait中的map函数返回一个值。实际上,它的签名是

def map[B](f: (A) ⇒ B): Seq[B]

它被设计为将一个函数应用于扩展Seq trait的集合的每个元素,并返回一个新的集合。

另一方面,在同一trait中,foreach具有以下签名:

def foreach(f: (A) ⇒ Unit): Unit

这意味着它被设计为执行具有副作用的函数。

在您的示例中,您将将值分配给“response”的操作视为副作用。如果您的实际目标是返回一个值(就像您似乎想做的那样),那么请使用map。


我的目标只是使用Seq元素创建一个列表(response),并不是想要返回一个值。 - legacy_shield
2
使用Seq元素创建一个列表(response),然后返回一个值。 :) - DeusEx

2
第二个版本更加明确其功能。
“map”传达了一种转换某些东西的意思,这正是你所做的事情。
相反,“foreach”执行超出其范围的操作,这并不太清楚。
换句话说,当我阅读“foreach”时,我必须查看整个范围,因为我知道你将执行一个副作用(因为“foreach”返回“Unit”)。
当我阅读“map”时,我可以自信地假设唯一涉及的表达式是我当前正在查看的表达式。
“map”降低了读者的负担,并使代码更容易理解。

2
  1. 使用foreach和元素的前置将生成一个以相反顺序排列的元素列表。

  2. 使用foreach时,必须将响应定义为var,而使用map时可以将响应定义为val。

我建议使用map,因为它更符合您的意图。


1

如果你想从循环操作中返回对象,我认为你应该避免使用forEach。而是选择foldLeft或其他类型的折叠操作。至于你的问题,如果你再次返回响应,则应该使用map,否则forEach应该能够正常工作。


1
使用foreach返回Unit(无)可以在进行副作用或类似操作时使用。如果要返回数据,则应使用map、flatMap、fold等方法。
scala> val l: List[String] = List("a", "b", "c")
l: List[String] = List(a, b, c)

scala> l.map(e => e.toUpperCase(java.util.Locale.ROOT))
res0: List[String] = List(A, B, C)

scala> l.foreach(e => println(e))
a
b
c

谢谢您的回答...但在我的情况下我有些困惑。我正在使用Seq的元素,在foreach循环中创建一个列表,但另一方面,我没有对元素本身进行任何更改(也没有对Seq的元素进行任何操作)。 - legacy_shield
为什么要重新创建一个列表?如果你只需要另一种列表类型,可以尝试使用 .to... 操作符(toList、toSeq、to[T])。 - jan0sch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接