.Toarray(New Myclass[0]) or .Toarray(New Myclass[Mylist.Size()])

.toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?

Counterintuitively, the fastest version, on Hotspot 8, is:

MyClass[] arr = myList.toArray(new MyClass[0]);

I have run a micro benchmark using jmh the results and code are below, showing that the version with an empty array consistently outperforms the version with a presized array. Note that if you can reuse an existing array of the correct size, the result may be different.

Benchmark results (score in microseconds, smaller = better):

Benchmark                      (n)  Mode  Samples    Score   Error  Units
c.a.p.SO29378922.preSize 1 avgt 30 0.025 ▒ 0.001 us/op
c.a.p.SO29378922.preSize 100 avgt 30 0.155 ▒ 0.004 us/op
c.a.p.SO29378922.preSize 1000 avgt 30 1.512 ▒ 0.031 us/op
c.a.p.SO29378922.preSize 5000 avgt 30 6.884 ▒ 0.130 us/op
c.a.p.SO29378922.preSize 10000 avgt 30 13.147 ▒ 0.199 us/op
c.a.p.SO29378922.preSize 100000 avgt 30 159.977 ▒ 5.292 us/op
c.a.p.SO29378922.resize 1 avgt 30 0.019 ▒ 0.000 us/op
c.a.p.SO29378922.resize 100 avgt 30 0.133 ▒ 0.003 us/op
c.a.p.SO29378922.resize 1000 avgt 30 1.075 ▒ 0.022 us/op
c.a.p.SO29378922.resize 5000 avgt 30 5.318 ▒ 0.121 us/op
c.a.p.SO29378922.resize 10000 avgt 30 10.652 ▒ 0.227 us/op
c.a.p.SO29378922.resize 100000 avgt 30 139.692 ▒ 8.957 us/op

For reference, the code:

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
public class SO29378922 {
@Param({"1", "100", "1000", "5000", "10000", "100000"}) int n;
private final List<Integer> list = new ArrayList<>();
@Setup public void populateList() {
for (int i = 0; i < n; i++) list.add(0);
}
@Benchmark public Integer[] preSize() {
return list.toArray(new Integer[n]);
}
@Benchmark public Integer[] resize() {
return list.toArray(new Integer[0]);
}
}

You can find similar results, full analysis, and discussion in the blog post Arrays of Wisdom of the Ancients. To summarize: the JVM and JIT compiler contains several optimizations that enable it to cheaply create and initialize a new correctly sized array, and those optimizations can not be used if you create the array yourself.

toArray() vs. toArray(new Object[0])

toArray() returns an array of Object. You have to cast every element of the array to your desired type.

The toArray(T[]) accepts a generic type and returns an array of the specific type. No need to cast the return value and/or the elements of the array.

As stated in the comments above, the toArray() method came pre-generics.

    List<String> list = new ArrayList<String>();
list.add("Alice");
list.add("Bob");

String[] strArray = list.toArray(new String[0]);
for (String str : strArray) {
System.out.println(str);
}

Object[] objArray = list.toArray();
for (Object obj : objArray) {
String str = (String) obj;
System.out.println(str);
}

What to pass to the Arrays instance method toArray(T[] a) method?

According to a findbugs report, this is the most efficient:

String[] addressesArray = addresses.toArray(new String[addresses.size()]);

I believe them ;)

.toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?

Counterintuitively, the fastest version, on Hotspot 8, is:

MyClass[] arr = myList.toArray(new MyClass[0]);

I have run a micro benchmark using jmh the results and code are below, showing that the version with an empty array consistently outperforms the version with a presized array. Note that if you can reuse an existing array of the correct size, the result may be different.

Benchmark results (score in microseconds, smaller = better):

Benchmark                      (n)  Mode  Samples    Score   Error  Units
c.a.p.SO29378922.preSize 1 avgt 30 0.025 ▒ 0.001 us/op
c.a.p.SO29378922.preSize 100 avgt 30 0.155 ▒ 0.004 us/op
c.a.p.SO29378922.preSize 1000 avgt 30 1.512 ▒ 0.031 us/op
c.a.p.SO29378922.preSize 5000 avgt 30 6.884 ▒ 0.130 us/op
c.a.p.SO29378922.preSize 10000 avgt 30 13.147 ▒ 0.199 us/op
c.a.p.SO29378922.preSize 100000 avgt 30 159.977 ▒ 5.292 us/op
c.a.p.SO29378922.resize 1 avgt 30 0.019 ▒ 0.000 us/op
c.a.p.SO29378922.resize 100 avgt 30 0.133 ▒ 0.003 us/op
c.a.p.SO29378922.resize 1000 avgt 30 1.075 ▒ 0.022 us/op
c.a.p.SO29378922.resize 5000 avgt 30 5.318 ▒ 0.121 us/op
c.a.p.SO29378922.resize 10000 avgt 30 10.652 ▒ 0.227 us/op
c.a.p.SO29378922.resize 100000 avgt 30 139.692 ▒ 8.957 us/op

For reference, the code:

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
public class SO29378922 {
@Param({"1", "100", "1000", "5000", "10000", "100000"}) int n;
private final List<Integer> list = new ArrayList<>();
@Setup public void populateList() {
for (int i = 0; i < n; i++) list.add(0);
}
@Benchmark public Integer[] preSize() {
return list.toArray(new Integer[n]);
}
@Benchmark public Integer[] resize() {
return list.toArray(new Integer[0]);
}
}

You can find similar results, full analysis, and discussion in the blog post Arrays of Wisdom of the Ancients. To summarize: the JVM and JIT compiler contains several optimizations that enable it to cheaply create and initialize a new correctly sized array, and those optimizations can not be used if you create the array yourself.

Convert List int[] of arrays to 2D - Array

List.toArray, with no arguments, returns a Object[], not a T[].

Object[] toArray()

That's because, in Java, writing new T[] (where T is a generic type) is not allowed, since it would require runtime access to the type T and we can't have that due to type erasure.

So they provide an overload to get around that. The overload that you're using looks like this.

<T> T[] toArray(T[] a)

You have to allocate the array and you have to make the new call, since you know what type of array you want. If you give Java an array of the appropriate type, it can use that array. If there's not enough elements in that array, it can use reflection to generate a bigger one of the same type.

So all you're doing is telling Java, at runtime, that the type of array you want is an array containing int[] (or a int[][]).

Now, as for why we make an array of zero elements, that's a bit more complicated (and I don't pretend to fully understand the optimizations in play either), but it's explained in this blog post. There would certainly be nothing wrong with giving it a new int[N][], where N is the length of your list. But, based on the optimizations currently available to the JVM, the zero array is recommended today.

List.toArray(Object[]) performance

Don't be concerned about performance of List.toArray(), its complexity is linear as it will resort to a single loop internally.

As it is implemented with Arrays.copyOf, which eventually comes to System.arraycopy, that is implemented in native code it could be potentially even faster than a java-level loop.



Related Topics



Leave a reply



Submit