2016-11-12 1 views
7

En Java, nous pouvons créer IntFunction<String[]> de référence constructeur de tableau 1D:références de méthode pour les tableaux multidimensionnels en Java 8

// both do the same thing 
    IntFunction<String[]> createArrayL = size -> new String[size]; 
    IntFunction<String[]> createArrayMR = String[]::new; 

Maintenant, je me demande pourquoi nous ne pouvons le faire avec un tableau 2D:

BiFunction<Integer, Integer, String[][]> createArray2DL = 
      (rows, cols) -> new String[rows][cols]; 

    // error: 
    BiFunction<Integer, Integer, String[][]> createArray2DMR = 
      String[][]::new; 

Bien sûr, nous pouvons écrire:

IntFunction<String[][]> createArray2DInvalidL = String[][]::new; 
    System.out.println(createArray2DInvalidL.apply(3)[0]); // prints null 

mais cela se comportera différemment de:

new String[3][3] 

car les tableaux de lignes ne seront pas initialisés. Donc, ma question est: pourquoi String[][]::new ne fonctionne pas pour les tableaux 2D (pour moi, cela ressemble à une incohérence dans la conception du langage)?

Répondre

8

Tout à fait un cas intéressant en effet. Le problème est que String[][]::new est une fonction avec une arité de 1 (c'est un constructeur d'un tableau de tableaux) et ne peut pas être traitée comme une BiFunction (arité de 2) et votre exemple new String[3][3] a deux paramètres au lieu deun.

Dans ce cas, createArray2DInvalidL.apply(3) est égal à appeler new String[3][];

Ce que vous cherchez peut-être est:

IntFunction<String[][]> createArray2D = n -> new String[n][n];

Les dimensions ne pas besoin d'avoir des longueurs égales et il semble que une hypothèse assez raisonnable.

http://4comprehension.com/multidimensional-arrays-vs-method-references/

+2

et pourquoi 'BiFunction createArray2DL = (a, b) -> Chaîne [] [] :: new;' produire une erreur ?? – user43968

+0

@ user43968 parce que dans votre expression lambda vous retournez une autre fonction '' 'BiFunction > createArray2DL = (a, b) -> Chaîne [] [] :: new;' '' –

1

Il n'y a pas d'incohérence ici. Si vous écrivez une déclaration comme

IntFunction<ElementType[]> f = ElementType[]::new; 

vous créez une fonction dont l'évaluation retourne un nouveau tableau à chaque entrée étant capable de contenir une référence de ElementType, initialisé à null. Cela ne change pas lorsque vous utilisez String[] pour ElementType.

Mais il a également été abordée explicitement dans The Java Language Specification, §15.13.3. Run-Time Evaluation of Method References:

Si le formulaire est Type [] k :: nouveau (k ≥ 1), le corps de la méthode d'appel a le même effet qu'une expression de création de tableau de la forme nouveau Type [size] [] k-1, où taille est le seul paramètre de la méthode d'appel. (La notation [] k indique une séquence de k paires de parenthèses.

Il n'y a pas de support pour une référence de méthode de création de tableau multidimensionnel rectangulaire, probablement parce qu'il n'y a pas de cas d'utilisation réel qui ait agi comme une force motrice. L'expression de création de tableau unidimensionnel peut être utilisée avec Stream.toArray(…), permettant une syntaxe plus concise que l'expression lambda équivalente, bien qu'il n'y ait pas de support spécial dans l'architecture sous-jacente, c.-à-d. int[]::new produit exactement le même code compilé que intArg -> new int[intArg]. Il n'y a pas de cas d'utilisation similaire pour une création de tableau à deux dimensions (ou même plus), donc il n'y a même pas d'interface fonctionnelle similaire pour une fonction consommant deux valeurs int ou plus et produisant un résultat de type référence.

+0

Mon le point était que puisque dans Java vous pouvez créer un tableau 2d par 'new Element [5] [6]' ou par 'new Element [5] []' (bien sûr dans le premier cas le compilateur allouera aussi des lignes pour moi) puis Java devrait permettre la même chose avec la référence du constructeur. Je suis perplexe car si le compilateur peut allouer des lignes dans l'expression 'new X [a] [b]', alors pourquoi pas dans l'événement 'X [] [] :: new' - si cela veut dire générer une expression lambda synthétique. – csharpfolk

+0

Personne ne dit qu'il ne serait pas possible d'écrire un compilateur capable de générer un tel code. Mais les concepteurs de langage n'ont pas ajouté de syntaxe pour cela. La syntaxe de la référence de méthode de création de tableau à une dimension se comporte de manière cohérente, même si le type d'élément est un tableau lui-même. Une syntaxe hypothétique de référence de méthode de création de tableau multidimensionnel rectangulaire doit différer de cela, car elle ne serait pas acceptable si 'X [] [] :: new' crée parfois des sous-réseaux et parfois non. Il n'y aurait pas beaucoup d'avantages de la syntaxe supplémentaire par rapport à une expression lambda équivalente. – Holger