在 Java 中扩展数组的最有效方法?
(如果之前有人问过这个问题,我深表歉意 - 我不敢相信它没有,但我找不到一个。也许我的搜索能力很弱。)
多年来,我“知道”Java 没有本机函数缩放数组(即将每个元素乘以一个常数)。所以我一直在这样做:
for (int i=0; i<array.length; i++) {
array[i] = array[i] * scaleFactor;
}
这实际上是最有效的方法吗(例如,在这个应用程序中,它是一个大约 10000 个双精度数的数组)?或者有更好的方法吗?
(Apologies if this has been asked before - I can't believe it hasn't, but I couldn't find one. Perhaps my search-fu is weak.)
For years I've "known" that Java has no native function to scale an array (i.e. multiply each element by a constant). So I've been doing this:
for (int i=0; i<array.length; i++) {
array[i] = array[i] * scaleFactor;
}
Is this actually the most efficient way (in this application, for example, it's an array of around 10000 doubles)? Or is there a better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
对我来说看起来绝对不错。我想不出更有效的方法。显然,尝试将该代码放在一个地方,而不是将实际代码放在各处,但除此之外,没有明显的问题。
Looks absolutely fine to me. I can't think of a more efficient way. Obviously try to put that code in one place rather than having the actual code all over the place, but other than that, no obvious problems.
我唯一能提供的其他建议是惰性扩展,您只需支付访问每个元素时的乘法成本;例如
,显然这仅在某些情况下更好:
在其他情况下,这是一种微观优化,对现代 CPU 没有真正的好处。
Only other suggestion I can offer is to lazily scale whereby you only pay the cost of multiplication on accessing each element; e.g.
Obviously this is only better in certain situations:
In other situations it's a micro-optimisation with no real benefit on modern CPUs.
“更好的方法”是编写
array[i] *=scaleFactor;
而不是array[i] = array[i] *scaleFactor;
。 :-)实际上,这只是语法糖 - 编译的输出(以及因此的性能)应该完全相同。正如乔恩所说,你将无法获得更好的性能,但就我个人而言,我每天都会减少打字量。
The "better way" is to write
array[i] *= scaleFactor;
instead ofarray[i] = array[i] * scaleFactor;
. :-)Really, that's just syntactic sugar though - the compiled output (and hence performance) should be exactly the same. As Jon says, you're not going to be able to get any better performance, but personally I'll take a reduction in typing any day.
除了 Adamski 和 Jon Skeet 之外,我唯一想补充的是,如果它恰好是一个整数/长整型数组,并且您按 2 的幂进行缩放,那么通过使用位移运算符可能会略有改进。不过,YMMV,因为它将取决于编译器(甚至可能取决于虚拟机)。
Only thing I can think to add in addition to Adamski and Jon Skeet is that if it happens to be an array of ints/longs and you're scaling by a power of 2, then you might get a slight improvement by using bitshift operators. YMMV though, since it will depend on the compiler (and possibly even the VM).
在 Java 8 中:
输出:
[3.0, 6.0, 9.0]
In Java 8:
output:
[3.0, 6.0, 9.0]
您可以使用线程来减少运行时间,但底线是您将包含此代码并让每个线程运行 for 循环的一部分,以便生成的程序与您的程序一样高效;它只是变得更快了
You could work with threads, to reduce the runtime, but the bottom line is you would include this code and let each thread run a part of the for loop so the resulting program is as efficient as yours; it's just made faster
对我来说看起来是最佳的。
不要陷入错误的优化,例如在循环外的最终字段中声明数组长度。这适用于集合,通过避免重复方法调用 .size() 和字符串,避免方法调用 .length(),但在数组上 .length 已经是公共最终字段。
此外,向后循环到零可能是一种汇编语言优化,但在像 Java 这样的高级语言中,VM 将处理任何明显的调整。
Looks optimal to me.
Don't fall for false optimisations like declaring the array length in a final field outside the loop. This works for Collections by avoiding repeat method calls to .size() and Strings avoiding method calls to .length() but on an array .length is already a public final field.
Also, looping backwards towards zero might be an assembly language optimisation but in a high level language like Java the VM will take care of any obvious tweaks.