forEach和map之间的性能差异

huangapple go评论56阅读模式
英文:

Performance difference between forEach and map

问题

以下是您要翻译的内容:

让我们假设我有一个产品的集合。我想遍历它们并复制它们的价格。

例如:

products.forEach {
    it.price = it.price * 2
}

有人要求我将forEach更改为map,以便使用map来遍历项目,从而具有完全相同的代码,但使用map效率更高。

有人能解释一下map为什么比forEach更快吗?此外,在较新的Kotlin版本中,您可以使用onEach迭代器。后者是否更加高效?

编辑:将forEach更改为map后,最终结果如下:

products.map {
    it.price = it.price * 2
}
英文:

Let us assume that I have a collection of Products. I want to iterate over them and duplicate its price.

For instance:

products.forEach {
    it.price = it.price * 2
}

I was asked to change forEach for map. So as to have the exact same code but use a map to iterate over the items since its more performant.

Can someone explain to me if and why is map faster than forEach? Also, in newer versions of Kotlin you can use a onEach iterator. Is this latter one even more performant?

Edit: when changing the forEach for a map, this is the end result:

products.map {
    it.price = it.price * 2
}

答案1

得分: 4

让我们看看你试图在这里实现什么。

通过使用forEach()(或者等效地,使用for循环),你正在原地更改你的集合:你仍然拥有相同的集合对象,但其元素已经被改变。

现在,你_可以_使用map()来做同样的事情,但这不是一个好主意(不更高效,而且不够清晰),因为虽然它确实遍历元素,map()的目的是从它们创建_另一个_集合

使用map()的正常方式应该是这样的:

val newProducts = products.map{ Product(it.price * 2) }

(显然,这不会编译,因为我不知道你的产品对象的正确名称,也不知道它的构造函数可能接受哪些参数。但我希望这能给你一个想法。)

这样做的效果是创建一个新的集合,其中包含从原始元素派生的新元素。然后你可以在后续代码中使用新集合。 (这可能是当你被要求使用map()时的预期效果。

以这种方式操作与原地更新集合相比,有优点和缺点。它需要更多的内存来存储新集合和新元素。但即使原始集合(和/或其元素)是不可变的,它仍然可以工作。它提高了线程安全性;其他线程可以继续使用原始集合,而不会受到你所做的影响,然后你可以使用你的新集合,而不会受到其他线程更改它的风险。而且不可变对象更容易理解,减少了错误的发生。

这导致了一种被称为函数式编程的编程风格,它强调不可变性而不是可变状态,避免副作用,并声明你想要的结果,而不是指示如何获得它们。Kotlin从Java继承了面向对象的范例,并添加了许多函数式编程工具,如map()filter()flatMap()reduce()associate(),以及函数类型、lambda表达式,以及使用val和不可变的ListMap类型的不可变性。这是一种不同的关于编程的方式,但学习一些关于它是很值得的;虽然很少有人使用Kotlin来编写“纯粹”的函数式程序,但我们许多人正在从使用一些函数式技巧中受益。

(我不一定是说在你的特定情况下使用函数式方法是值得的;我们需要了解更多的上下文。但我希望你现在意识到了这种可能性!)

英文:

Let's look at what you're trying to achieve here.

By using forEach() (or, equivalently, a for loop) you're changing your collection in-place: you still have the same collection object, but its elements have been mutated.

Now, you could use map() to do the same, but that wouldn't be a good idea (no more efficient, and less clear to read), because while it does iterate through the elements, the point of map() is to create another collection from them.

The normal way to use map() would be along the lines of:

val newProducts = products.map{ Product(it.price * 2) }

(Obviously, this won't compile, because I don't know the proper name of your product object, nor what parameters its constructor might take. But I hope it gives an idea.)

What this does is to create a new collection, holding new elements derived from the original ones. You would then go on to use the new collection in the following code. (This may be what was intended when you were asked to use map().)

Doing it this way has advantages and disadvantages over updating the collection in-place. It takes more memory, to store the new collection and its new elements. But it works even if the original collection (and/or its elements) are immutable. It improves thread-safety; any other threads can continue to use the original collection without being affected by what you're doing, and you can then use your new one without the risk of other threads changing it. And immutable objects can be easier to reason about, and lead to fewer bugs.

This leads to a style of programming known as functional programming, which stresses immutability over mutable state, avoiding side-effects, and declaring the results you want rather than instructing how to get them. Kotlin adds many functional programming tools to the object-oriented paradigm it inherited from Java; as well as map(), functions like filter(), flatMap(), reduce(), associate(), along with function types, lambdas, and the easy use of immutability with val and the immutable List and Map types. This is a different way of thinking about programming, but it's well worth learning a bit about; while few people use Kotlin to write ‘pure’ functional programs, many of us are finding benefits from using some functional techniques.


(I'm not necessarily saying that it's worth using a functional approach in your particular case; we'd need to know a lot more context. But I hope you're now aware of the possibility!)

huangapple
  • 本文由 发表于 2023年2月24日 15:16:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75553572.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定