Java Language Création et initialisation de tableaux


Exemple

Cas de base

int[]   numbers1 = new int[3];                 // Array for 3 int values, default value is 0
int[]   numbers2 = { 1, 2, 3 };                // Array literal of 3 int values
int[]   numbers3 = new int[] { 1, 2, 3 };      // Array of 3 int values initialized
int[][] numbers4 = { { 1, 2 }, { 3, 4, 5 } };  // Jagged array literal
int[][] numbers5 = new int[5][];               // Jagged array, one dimension 5 long
int[][] numbers6 = new int[5][4];              // Multidimensional array: 5x4

Les tableaux peuvent être créés en utilisant n'importe quel type de primitive ou de référence.

float[]  boats = new float[5];          // Array of five 32-bit floating point numbers.
double[] header = new double[] { 4.56, 332.267, 7.0, 0.3367, 10.0 };
                                       // Array of five 64-bit floating point numbers.
String[] theory = new String[] { "a", "b", "c" };
                                       // Array of three strings (reference type).
Object[] dArt = new Object[] { new Object(), "We love Stack Overflow.", new Integer(3) };
                                       // Array of three Objects (reference type).

Pour le dernier exemple, notez que les sous-types du type de tableau déclaré sont autorisés dans le tableau.

Les tableaux pour les types définis par l'utilisateur peuvent également être construits de manière similaire aux types primitifs

UserDefinedClass[] udType = new UserDefinedClass[5];

Tableaux, collections et flux

Java SE 1.2
// Parameters require objects, not primitives

// Auto-boxing happening for int 127 here
Integer[]       initial        = { 127, Integer.valueOf( 42 ) };
List<Integer>   toList         = Arrays.asList( initial );  // Fixed size! 

// Note: Works with all collections
Integer[]       fromCollection = toList.toArray( new Integer[toList.size()] );

//Java doesn't allow you to create an array of a parameterized type
List<String>[]  list = new ArrayList<String>[2];  // Compilation error!
Java SE 8
// Streams - JDK 8+
Stream<Integer> toStream       = Arrays.stream( initial );
Integer[]       fromStream     = toStream.toArray( Integer[]::new );

Introduction

Un tableau est une structure de données contenant un nombre fixe de valeurs primitives ou des références à des instances d'objets.

Chaque élément d'un tableau est appelé un élément et chaque élément est accessible par son index numérique. La longueur d'un tableau est établie lorsque le tableau est créé:

int size = 42;
int[] array = new int[size];

La taille d'un tableau est fixée à l'exécution lors de l'initialisation. Il ne peut pas être modifié après l'initialisation. Si la taille doit être mutable à l'exécution, une classe Collection telle ArrayList doit être utilisée à la place. ArrayList stocke des éléments dans un tableau et prend en charge le redimensionnement en allouant un nouveau tableau et en copiant des éléments de l'ancien tableau.

Si le tableau est de type primitif, c'est-à-dire

int[] array1 = { 1,2,3 };
int[] array2 = new int[10];

les valeurs sont stockées dans le tableau lui-même. En l'absence d'initialiseur (comme dans array2 ci-dessus), la valeur par défaut attribuée à chaque élément est 0 (zéro).

Si le type de tableau est une référence d'objet, comme dans

SomeClassOrInterface[] array = new SomeClassOrInterface[10];

le tableau contient alors des références à des objets de type SomeClassOrInterface . Ces références peuvent faire référence à une instance de SomeClassOrInterface ou de toute sous-classe (pour les classes) ou à la classe d'implémentation (pour les interfaces) de SomeClassOrInterface . Si la déclaration de tableau n'a pas d'initialiseur, la valeur par défaut de null est affectée à chaque élément.

Comme tous les tableaux sont int -indexed, la taille d'un tableau doit être spécifiée par un int . La taille du tableau ne peut pas être spécifiée comme un long :

long size = 23L;
int[] array = new int[size]; // Compile-time error:
                             // incompatible types: possible lossy conversion from
                             // long to int

Les tableaux utilisent un système d' index basé sur zéro , ce qui signifie que l'indexation commence à 0 et se termine à la length - 1 .

Par exemple, l'image suivante représente un tableau de taille 10 . Ici, le premier élément est à l'indice 0 et le dernier élément à l'indice 9 , au lieu que le premier élément soit à l'indice 1 et le dernier élément à l'index 10 (voir la figure ci-dessous).

Un tableau de 10 éléments

Les accès aux éléments des tableaux se font à temps constant . Cela signifie que l'accès au premier élément du tableau a le même coût (en temps) d'accès au deuxième élément, au troisième élément, etc.

Java offre plusieurs façons de définir et d'initialiser des tableaux, notamment des notations littérales et des constructeurs . Lors de la déclaration de tableaux utilisant le new Type[length] , chaque élément sera initialisé avec les valeurs par défaut suivantes:

Création et initialisation de tableaux de type primitif

int[] array1 = new int[] { 1, 2, 3 }; // Create an array with new operator and 
                                      // array initializer.
int[] array2 = { 1, 2, 3 };           // Shortcut syntax with array initializer.
int[] array3 = new int[3];            // Equivalent to { 0, 0, 0 }
int[] array4 = null;                  // The array itself is an object, so it
                                      // can be set as null.

Lors de la déclaration d'un tableau, [] apparaîtra dans le type au début de la déclaration (après le nom du type) ou dans le déclarateur d'une variable particulière (après le nom de la variable), ou les deux:

int array5[];       /* equivalent to */  int[] array5;
int a, b[], c[][];  /* equivalent to */  int a; int[] b; int[][] c;
int[] a, b[];       /* equivalent to */  int[] a; int[][] b;
int a, []b, c[][];  /* Compilation Error, because [] is not part of the type at beginning
                       of the declaration, rather it is before 'b'. */    
// The same rules apply when declaring a method that returns an array:
int foo()[] { ... } /* equivalent to */  int[] foo() { ... }

Dans l'exemple suivant, les deux déclarations sont correctes et peuvent être compilées et exécutées sans aucun problème. Cependant, la convention de codage Java et le guide de style Java de Google découragent tous les deux le formulaire entre parenthèses après le nom de la variable. Les crochets identifient le type de tableau et doivent apparaître avec la désignation du type . La même chose devrait être utilisée pour les signatures de retour de méthode.

float array[]; /* and */ int foo()[] { ... } /* are discouraged */
float[] array; /* and */ int[] foo() { ... } /* are encouraged */

Le type déconseillé est destiné à accueillir les utilisateurs de la transition C , qui sont familiarisés avec la syntaxe de C qui contient les crochets après le nom de la variable.

En Java, il est possible d'avoir des tableaux de taille 0 :

int[] array = new int[0]; // Compiles and runs fine.
int[] array2 = {};        // Equivalent syntax.

Cependant, comme il s’agit d’un tableau vide, aucun élément ne peut être lu ou assigné:

array[0] = 1;     // Throws java.lang.ArrayIndexOutOfBoundsException.
int i = array2[0]; // Also throws ArrayIndexOutOfBoundsException.

De tels tableaux vides sont généralement utiles en tant que valeurs de retour, de sorte que le code appelant ne doit se préoccuper que du traitement d'un tableau, plutôt que d'une valeur null potentielle pouvant mener à une NullPointerException .

La longueur d'un tableau doit être un entier non négatif:

int[] array = new int[-1]; // Throws java.lang.NegativeArraySizeException

La taille du tableau peut être déterminée en utilisant un champ final public appelé length :

System.out.println(array.length); // Prints 0 in this case.

Remarque : array.length renvoie la taille réelle du tableau et non le nombre d'éléments de tableau auxquels une valeur a été attribuée, contrairement à ArrayList.size() qui renvoie le nombre d'éléments de tableau auxquels une valeur a été attribuée.

Création et initialisation de tableaux multidimensionnels

La manière la plus simple de créer un tableau multidimensionnel est la suivante:

int[][] a = new int[2][3];

Il créera deux tableaux int trois longueurs: a[0] et a[1] . Ceci est très similaire à l'initialisation classique de style C des tableaux multidimensionnels rectangulaires.

Vous pouvez créer et initialiser en même temps:

int[][] a = { {1, 2}, {3, 4}, {5, 6} };

Contrairement à C , où seuls les tableaux rectangulaires multidimensionnels sont pris en charge, les tableaux internes ne doivent pas nécessairement être de même longueur, ni même définis:

int[][] a = { {1}, {2, 3}, null };

Ici, a[0] est un tableau int longueur, tandis a[1] est un tableau int deux longueurs et a[2] est null . Les tableaux comme celui-ci sont appelés tableaux irréguliers ou tableaux déchiquetés , c’est-à-dire qu’ils sont des tableaux de tableaux. Les tableaux multidimensionnels en Java sont implémentés en tant que tableaux de tableaux, c'est-à-dire que le array[i][j][k] est équivalent à ((array[i])[j])[k] . Contrairement à C # , le array[i,j] syntaxe array[i,j] n'est pas pris en charge en Java.

Représentation multidimensionnelle des tableaux en Java

Représentation visuelle d'un tableau multidimensionnel Java

Source - Live on Ideone

Création et initialisation de tableaux de type référence

String[] array6 = new String[] { "Laurel", "Hardy" }; // Create an array with new 
                                                      // operator and array initializer.
String[] array7 = { "Laurel", "Hardy" };              // Shortcut syntax with array 
                                                      // initializer.
String[] array8 = new String[3];                      // { null, null, null }
String[] array9 = null;                               // null

Vivre sur Ideone

En plus des littéraux et des primitives de String présentés ci-dessus, la syntaxe de raccourci pour l'initialisation du tableau fonctionne également avec les types d' Object canoniques:

Object[] array10 = { new Object(), new Object() };

Les tableaux étant covariants, un tableau de type référence peut être initialisé en tant que tableau d'une sous-classe, bien qu'une ArrayStoreException soit émise si vous essayez de définir un élément sur autre chose qu'une String :

Object[] array11 = new String[] { "foo", "bar", "baz" };
array11[1] = "qux"; // fine
array11[1] = new StringBuilder(); // throws ArrayStoreException

La syntaxe de raccourci ne peut pas être utilisée pour cela car la syntaxe de raccourci aurait un type implicite d' Object[] .

Un tableau peut être initialisé avec des éléments nuls en utilisant String[] emptyArray = new String[0] . Par exemple, un tableau comme celui-ci est utilisé pour créer un Array partir d'une Collection lorsque la méthode nécessite le type d'exécution d'un objet.

Dans les deux types de primitive et de référence, une initialisation de tableau vide (par exemple, String[] array8 = new String[3] ) initialisera le tableau avec la valeur par défaut pour chaque type de données .

Création et initialisation de tableaux de type générique

Dans les classes génériques, les tableaux de types génériques ne peuvent pas être initialisés comme ceci en raison de l' effacement de type :

public class MyGenericClass<T> {
    private T[] a;

    public MyGenericClass() {
        a = new T[5]; // Compile time error: generic array creation
    }
}

Au lieu de cela, ils peuvent être créés en utilisant l'une des méthodes suivantes: (notez que cela générera des avertissements non vérifiés)

  1. En créant un tableau Object et en le convertissant en type générique:

    a = (T[]) new Object[5];
    

    C'est la méthode la plus simple, mais comme le tableau sous-jacent est toujours de type Object[] , cette méthode ne fournit pas de sécurité de type. Par conséquent, cette méthode de création d'un tableau est mieux utilisée que dans la classe générique - non exposée publiquement.

  2. En utilisant Array.newInstance avec un paramètre de classe:

    public MyGenericClass(Class<T> clazz) {
        a = (T[]) Array.newInstance(clazz, 5);
    }
    

    Ici, la classe de T doit être explicitement passée au constructeur. Le type de retour de Array.newInstance est toujours Object . Cependant, cette méthode est plus sûre car le tableau nouvellement créé est toujours de type T[] et peut donc être externalisé en toute sécurité.

Remplissage d'un tableau après l'initialisation

Java SE 1.2

Arrays.fill() peut être utilisé pour remplir un tableau avec la même valeur après l'initialisation:

Arrays.fill(array8, "abc");        // { "abc", "abc", "abc" }

Vivre sur Ideone

fill() peut également attribuer une valeur à chaque élément de la plage spécifiée du tableau:

Arrays.fill(array8, 1, 2, "aaa");  // Placing "aaa" from index 1 to 2.

Vivre sur Ideone

Java SE 8

Depuis la version 8 de Java, la méthode setAll et son équivalent Concurrent parallelSetAll peuvent être utilisés pour définir chaque élément d'un tableau sur des valeurs générées. Ces méthodes sont passées à une fonction de générateur qui accepte un index et renvoie la valeur souhaitée pour cette position.

L'exemple suivant crée un tableau d'entiers et définit tous ses éléments sur leur valeur d'index respective:

int[] array = new int[5];
Arrays.setAll(array, i -> i); // The array becomes { 0, 1, 2, 3, 4 }.

Vivre sur Ideone

Déclaration séparée et initialisation des tableaux

La valeur d'un index pour un élément de tableau doit être un nombre entier (0, 1, 2, 3, 4, ...) et inférieur à la longueur du tableau (les index sont basés sur zéro). Sinon, une exception ArrayIndexOutOfBoundsException sera lancée:

int[] array9;             // Array declaration - uninitialized
array9 = new int[3];      // Initialize array  - { 0, 0, 0 }
array9[0] = 10;           // Set index 0 value - { 10, 0, 0 }
array9[1] = 20;           // Set index 1 value - { 10, 20, 0 }
array9[2] = 30;           // Set index 2 value - { 10, 20, 30 }

Les tableaux ne peuvent pas être réinitialisés avec la syntaxe de raccourci de l'initialiseur de tableau

Il n'est pas possible de réinitialiser un tableau via une syntaxe de raccourci avec un initialiseur de tableau, car un initialiseur de tableau ne peut être spécifié que dans une déclaration de champ ou une déclaration de variable locale ou dans une expression de création de tableau.

Cependant, il est possible de créer un nouveau tableau et de l'assigner à la variable utilisée pour référencer l'ancien tableau. Bien que cela entraîne la ré-initialisation du tableau référencé par cette variable, le contenu de la variable est un tableau complètement nouveau. Pour ce faire, le new opérateur peut être utilisé avec un initialiseur de tableau et affecté à la variable de tableau:

// First initialization of array
int[] array = new int[] { 1, 2, 3 };

// Prints "1 2 3 ".
for (int i : array) {
    System.out.print(i + " ");
}

// Re-initializes array to a new int[] array.
array = new int[] { 4, 5, 6 };

// Prints "4 5 6 ".
for (int i : array) {
    System.out.print(i + " ");
}

array = { 1, 2, 3, 4 }; // Compile-time error! Can't re-initialize an array via shortcut 
                        // syntax with array initializer.

Vivre sur Ideone