In Java we may create IntFunction<String[]>
from 1D array constructor reference:
// both do the same thing
IntFunction<String[]> createArrayL = size -> new String[size];
IntFunction<String[]> createArrayMR = String[]::new;
Now I wonder why we cannot do this with a 2D array:
BiFunction<Integer, Integer, String[][]> createArray2DL =
(rows, cols) -> new String[rows][cols];
// error:
BiFunction<Integer, Integer, String[][]> createArray2DMR =
String[][]::new;
Of course we may write:
IntFunction<String[][]> createArray2DInvalidL = String[][]::new;
System.out.println(createArray2DInvalidL.apply(3)[0]); // prints null
but this will behave differently than:
new String[3][3]
because row arrays will not be initialized.
So my question is: why String[][]::new
doesn't work for 2D arrays (for me it looks like an inconsistency in language design)?
Quite an interesting case indeed.
The problem is that String[][]::new
is a function with an arity of 1(it's a constructor of an array of arrays) and can't be treated as a BiFunction(arity of 2) and your example new String[3][3]
has two parameters instead of one.
In this case,
createArray2DInvalidL.apply(3)
is equal to calling new String[3][];
What you might be looking for is:
IntFunction<String[][]> createArray2D = n -> new String[n][n];
Dimensions don't need to have equal lengths and it sounds like a pretty reasonable assumption.
http://4comprehension.com/multidimensional-arrays-vs-method-references/
There is no inconsistency here. If you write a statement like
IntFunction<ElementType[]> f = ElementType[]::new;
you create a function whose evaluation will return a new array with each entry being capable of holding a reference of ElementType
, initialized to null
. This doesn’t change, when you use String[]
for ElementType
.
But it also has been addressed explicitly in The Java Language Specification, §15.13.3. Run-Time Evaluation of Method References:
If the form is Type[]k :: new (k ≥ 1), then the body of the invocation method has the same effect as an array creation expression of the form new Type [ size ] []k-1, where size is the invocation method’s single parameter. (The notation []k indicates a sequence of k bracket pairs.)
There is no support for a rectangular multi-dimensional array creation method reference, most likely, because there is no actual use case that acted as a driving force. The one-dimensional array creation expression can be used together with Stream.toArray(…)
, allowing a more concise syntax than the equivalent lambda expression, despite there is no special support in the underlying architecture, i.e. int[]::new
produces exactly the same compiled code as intArg -> new int[intArg]
. There is no similar use case for a two (or even more) dimensional array creation, so there isn’t even a similar functional interface for a function consuming two or more int
value and producing a reference type result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With