在构造函数中设置Java Collection的大小更好吗?

dev*_*ull 1 java collections microbenchmark jmh

如果我知道那个点的大小,那么传递CollectionCollection构造函数的大小是否更好?扩展Collection和分配/重新分配的节约效果是否显着?

如果我知道最小尺寸Collection而不是上限,该怎么办?至少在最小尺寸的情况下仍然值得创造吗?

Tim*_*m B 5

不同的集合对此有不同的性能影响,对于ArrayList,保存可以非常明显.

import java.util.*;
public class Main{
public static void main(String[] args){
  List<Integer> numbers = new ArrayList<Integer>(5);
  int max = 1000000;
  // Warmup
  for (int i=0;i<max;i++) {
    numbers.add(i);
  }

  long start = System.currentTimeMillis();
  numbers = new ArrayList<Integer>(max);
  for (int i=0;i<max;i++) {
    numbers.add(i);
  }
  System.out.println("Preall: "+(System.currentTimeMillis()-start));

  start = System.currentTimeMillis();
  numbers = new ArrayList<Integer>(5);
  for (int i=0;i<max;i++) {
    numbers.add(i);
  }
  System.out.println("Resizing: "+(System.currentTimeMillis()-start));

}
}
Run Code Online (Sandbox Code Playgroud)

结果:

Preall: 26
Resizing: 58
Run Code Online (Sandbox Code Playgroud)

以max设置为10000000的值的10倍运行给出:

Preall: 510
Resizing: 935
Run Code Online (Sandbox Code Playgroud)

所以你甚至可以看到不同尺寸的比例保持不变.

这几乎是最糟糕的测试,但是一次填充一个数组元素非常常见,你可以看到速度差异大约为2*.

  • @MarkoTopolnik你为什么要算这个呢?;-)更严重的是,这只涉及内存方面,而不是调整大小的性能成本(我没有测量过).时间快点jmh? (3认同)

Mar*_*nik 5

好的,这是我的 jmh 代码:

@OutputTimeUnit(TimeUnit.MICROSECONDS)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 3, time = 1)
@Measurement(iterations = 3, time = 1)
@Fork(3)
public class Comparison
{
  static final int size = 1_000;
  @GenerateMicroBenchmark
  public List<?> testSpecifiedSize() {
    final ArrayList<Integer> l = new ArrayList(size);
    for (int i = 0; i < size; i++) l.add(1);
    return l;
  }

  @GenerateMicroBenchmark
  public List<?> testDefaultSize() {
    final ArrayList<Integer> l = new ArrayList();
    for (int i = 0; i < size; i++) l.add(1);
    return l;
  }
}
Run Code Online (Sandbox Code Playgroud)

我的结果size = 10_000

Benchmark             Mode Thr    Cnt  Sec         Mean   Mean error    Units
testDefaultSize       avgt   1      9    1       80.770        2.095  usec/op
testSpecifiedSize     avgt   1      9    1       50.060        1.078  usec/op
Run Code Online (Sandbox Code Playgroud)

结果size = 1_000

Benchmark             Mode Thr    Cnt  Sec         Mean   Mean error    Units
testDefaultSize       avgt   1      9    1        6.208        0.131  usec/op
testSpecifiedSize     avgt   1      9    1        4.900        0.078  usec/op
Run Code Online (Sandbox Code Playgroud)

我的解读:

  • presizing在默认大小上有一些优势;
  • 边缘并不那么壮观;
  • 添加到列表的任务所花费的绝对时间是微不足道的。

我的结论:

如果这让您感觉心脏周围更温暖,请添加初始尺寸,但客观地说,您的客户极不可能注意到差异。

  • @assylias,TimB 我想说我们可以把它写成一种风格偏好......客观测量不支持将预定义作为相关最佳实践的规则,但至少它们给了你*一些东西*。因此,我们一方面有一个次要的代码风格问题(到处都有更多的代码),另一方面有一个次要的性能问题。这归结为您对在构造函数调用中没有额外代码的重视程度。一方面,我认为它比我可能从中获得的相当抽象的优势更重要。 (2认同)