在 Java 中扩展数组的最有效方法?

发布于 2024-12-10 07:51:37 字数 288 浏览 0 评论 0原文

(如果之前有人问过这个问题,我深表歉意 - 我不敢相信它没有,但我找不到一个。也许我的搜索能力很弱。)

多年来,我“知道”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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

落日海湾 2024-12-17 07:51:37

对我来说看起来绝对不错。我想不出更有效的方法。显然,尝试将该代码放在一个地方,而不是将实际代码放在各处,但除此之外,没有明显的问题。

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.

似梦非梦 2024-12-17 07:51:37

我唯一能提供的其他建议是惰性扩展,您只需支付访问每个元素时的乘法成本;例如

public class MyArray {
  private final double[] arr;
  private double scale = 1.0;

  public MyArray(double[] arr) {
    this.arr = arr;
  }

  public double getScale() {
    return scale;
  }

  public void setScale(double scale) {
    this.scale = scale;
  }

  public double elementAt(int i) {
    return arr[i] * scale;
  }
}

,显然这仅在某些情况下更好:

  • 当您的数组很大并且
  • 您只访问几个元素并且
  • 您通常只访问这些元素一次。

在其他情况下,这是一种微观优化,对现代 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.

public class MyArray {
  private final double[] arr;
  private double scale = 1.0;

  public MyArray(double[] arr) {
    this.arr = arr;
  }

  public double getScale() {
    return scale;
  }

  public void setScale(double scale) {
    this.scale = scale;
  }

  public double elementAt(int i) {
    return arr[i] * scale;
  }
}

Obviously this is only better in certain situations:

  • When your array is huge AND
  • You are only accessing a few elements AND
  • You are typically accessing these elements once.

In other situations it's a micro-optimisation with no real benefit on modern CPUs.

我一向站在原地 2024-12-17 07:51:37

“更好的方法”是编写 array[i] *=scaleFactor; 而不是 array[i] = array[i] *scaleFactor;。 :-)

实际上,这只是语法糖 - 编译的输出(以及因此的性能)应该完全相同。正如乔恩所说,你将无法获得更好的性能,但就我个人而言,我每天都会减少打字量。

The "better way" is to write array[i] *= scaleFactor; instead of array[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.

汹涌人海 2024-12-17 07:51:37

除了 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).

甩你一脸翔 2024-12-17 07:51:37

在 Java 8 中:

double coef = 3.0;
double[] x1 = {1,2,3};
double[] x2 = DoubleStream.of(x1).map(d->d*coef).toArray();

System.out.println(Arrays.toString(x2));

输出:[3.0, 6.0, 9.0]

In Java 8:

double coef = 3.0;
double[] x1 = {1,2,3};
double[] x2 = DoubleStream.of(x1).map(d->d*coef).toArray();

System.out.println(Arrays.toString(x2));

output: [3.0, 6.0, 9.0]

梦屿孤独相伴 2024-12-17 07:51:37

您可以使用线程来减少运行时间,但底线是您将包含此代码并让每个线程运行 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

水水月牙 2024-12-17 07:51:37

对我来说看起来是最佳的。

不要陷入错误的优化,例如在循环外的最终字段中声明数组长度。这适用于集合,通过避免重复方法调用 .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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文