5

I had the following piece of code that IntelliJ suggested I should change:

String[] normalizedNames = rawToNormalized.values().stream().toArray(String[]::new);

into

String[] normalizedAliases = rawToNormalized.values().toArray(new String[0]);

Aleksey Shipilёv's post (https://shipilev.net/blog/2016/arrays-wisdom-ancients/) suggested:

toArray(new T[0]) seems faster, safer, and contractually cleaner, and therefore should be the default choice now."

Can someone please elaborate how exactly toArray(new String[0]) differs from toArray(String[]::new) by going from stream and using toArray without Collector.

Can toArray(new String[0]) still be used in the stream? Will it still be a more performant/better choice?

Naman
  • 23,555
  • 22
  • 173
  • 290
QuirkyBit
  • 507
  • 3
  • 17
  • 2
    _opinion based_? really? java-11 added `Collection::toArray` with the exact pattern of an empty array for a _reason_. Voting to re-open. – Eugene Oct 28 '19 at 14:52
  • I would love to know if they are equivalent or if there is an actual difference in the compiler implementation. Why would the IDE suggest the change? – QuirkyBit Oct 28 '19 at 15:02
  • 1
    Mind that Shipilёv did not discuss the Stream op. I don’t know about IntelliJ, but the Netbeans IDE loves to suggest code transformations, just because it can. Sometimes, after the transformation it suggests converting it back to the original form (just for the same reason). For most collections, there won’t be a significant difference between these alternatives. The second variant omits the (rather cheap) construction of a Stream instance, that’s it. Only for concurrent collections, there might be differences, but since this is implementation dependent, I wouldn’t guess, which will be faster. – Holger Oct 28 '19 at 16:40
  • 2
    One has to keep in mind that with recent changes in the OpenJDK (14), it may be that in the future `new String[normalizedAliases.size()]` is faster if the input is a Set or Map. Nobody benchmarked the new code yet, as far as I'm aware. Cf. https://hg.openjdk.java.net/jdk/jdk/rev/1afe0cb93482 Bottom line: write a JMH test for it :) – D. Kovács Oct 28 '19 at 17:45
  • 1
    @D.Kovács this optimization only affects `HashMap`, not every `Set` or `Map`. Further, it doesn’t change the fundamental points described in Shipilёv’s article. For that, a JVM change would be needed. – Holger Oct 29 '19 at 10:04

1 Answers1

1

I would follow intelliJ as one simple reason :

Why you trasform your list to stream to create an array. In the other side you can transform that list to an array directly.

Can someone please elaborate how exactly toArray(new String[0]) differs from toArray(String[]::new) and if toArray(new String[0]) still the more performant/better choice?

The idea behind the intelliJ warning is about using stream befor toArray and not the way of using toArray

YCF_L
  • 49,027
  • 13
  • 75
  • 115