Introduction
En programmation Java, travailler avec différentes structures de données est essentiel pour un développement de programme efficace. Les tableaux (Arrays) et les listes (Lists) sont deux structures de données fondamentales qui servent des objectifs différents. Alors que les tableaux fournissent un stockage de taille fixe, les listes offrent une flexibilité avec un dimensionnement dynamique et des méthodes utilitaires supplémentaires.
Ce tutoriel se concentre sur la conversion des tableaux Java en listes mutables sans modifier les données du tableau d'origine. À la fin de ce lab, vous comprendrez la relation entre les tableaux et les listes et apprendrez des techniques pratiques pour convertir entre eux tout en maintenant l'intégrité des données.
Comprendre les tableaux (Arrays) et les listes (Lists) en Java
Dans cette étape, nous allons explorer les différences fondamentales entre les tableaux (Arrays) et les listes (Lists) en Java en créant des exemples des deux. Nous examinerons également comment accéder à leurs éléments et les afficher.
Création d'un projet Java
Commençons par créer un simple fichier Java pour travailler :
Ouvrez le terminal et accédez au répertoire du projet :
cd ~/projectCréez un nouveau répertoire pour nos fichiers Java :
mkdir -p src/main/java cd src/main/javaCréez un nouveau fichier Java appelé
ArrayListDemo.javaen utilisant le WebIDE. Cliquez sur l'icône Explorer dans le WebIDE, accédez àproject/src/main/java, faites un clic droit et sélectionnez "New File". Nommez-leArrayListDemo.java.Ajoutez le code suivant au fichier :
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
System.out.println("Java Arrays vs Lists Example");
System.out.println("============================");
// Creating an array of integers
int[] numbersArray = {1, 2, 3, 4, 5};
// Displaying array contents
System.out.println("Array contents: " + Arrays.toString(numbersArray));
// Accessing array elements by index
System.out.println("Array element at index 2: " + numbersArray[2]);
// Creating a List using ArrayList
List<Integer> numbersList = new ArrayList<>();
numbersList.add(1);
numbersList.add(2);
numbersList.add(3);
numbersList.add(4);
numbersList.add(5);
// Displaying list contents
System.out.println("List contents: " + numbersList);
// Accessing list elements by index
System.out.println("List element at index 2: " + numbersList.get(2));
// Demonstrating List flexibility - adding a new element
numbersList.add(6);
System.out.println("List after adding element: " + numbersList);
// Demonstrating List flexibility - removing an element
numbersList.remove(1); // Removes element at index 1
System.out.println("List after removing element at index 1: " + numbersList);
}
}
Compilez et exécutez le programme Java :
cd ~/project javac src/main/java/ArrayListDemo.java java -cp src/main/java ArrayListDemo
Vous devriez voir une sortie similaire à celle-ci :
Java Arrays vs Lists Example
============================
Array contents: [1, 2, 3, 4, 5]
Array element at index 2: 3
List contents: [1, 2, 3, 4, 5]
List element at index 2: 3
List after adding element: [1, 2, 3, 4, 5, 6]
List after removing element at index 1: [1, 3, 4, 5, 6]
Différences clés entre les tableaux (Arrays) et les listes (Lists)
Flexibilité de la taille :
- Les tableaux ont une taille fixe qui ne peut pas être modifiée après la création.
- Les listes peuvent croître ou se réduire dynamiquement selon les besoins.
Opérations disponibles :
- Les tableaux ont des fonctionnalités intégrées limitées.
- Les listes fournissent de nombreuses méthodes pour ajouter, supprimer et manipuler des éléments.
Contraintes de type :
- Les tableaux peuvent stocker des primitives ou des objets.
- Les listes ne peuvent stocker que des objets (mais l'autoboxing permet de stocker des primitives indirectement).
Comprendre ces différences vous aide à choisir la structure de données appropriée pour vos besoins spécifiques.
Conversion des tableaux (Arrays) en listes (Lists)
Maintenant que nous comprenons les bases des tableaux (Arrays) et des listes (Lists), explorons différentes manières de convertir un tableau en une liste. Nous nous concentrerons particulièrement sur la création de listes mutables à partir de tableaux.
Créer un nouveau fichier Java
Créez un nouveau fichier Java appelé
ArrayToListConversion.javadans le même répertoire :Depuis le WebIDE, accédez à
project/src/main/java, faites un clic droit et sélectionnez "New File". Nommez-leArrayToListConversion.java.Ajoutez le code suivant au fichier :
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ArrayToListConversion {
public static void main(String[] args) {
System.out.println("Converting Arrays to Lists");
System.out.println("=========================");
// Create an array of Strings
String[] fruitsArray = {"Apple", "Banana", "Cherry", "Date", "Elderberry"};
System.out.println("Original array: " + Arrays.toString(fruitsArray));
// Method 1: Using Arrays.asList() - Creates a fixed-size list
System.out.println("\nMethod 1: Arrays.asList()");
List<String> fruitsListFixed = Arrays.asList(fruitsArray);
System.out.println("List created with Arrays.asList(): " + fruitsListFixed);
// Try to modify the list
System.out.println("Changing element at index 0 to 'Apricot'");
fruitsListFixed.set(0, "Apricot");
System.out.println("List after change: " + fruitsListFixed);
System.out.println("Original array after List change: " + Arrays.toString(fruitsArray));
// This will cause UnsupportedOperationException
try {
System.out.println("Trying to add a new element to the fixed-size list...");
fruitsListFixed.add("Fig");
} catch (UnsupportedOperationException e) {
System.out.println("Error: Cannot add to fixed-size list!");
}
// Reset the array for next example
fruitsArray[0] = "Apple";
// Method 2: Using new ArrayList<>(Arrays.asList()) - Creates a mutable list
System.out.println("\nMethod 2: new ArrayList<>(Arrays.asList())");
List<String> fruitsList = new ArrayList<>(Arrays.asList(fruitsArray));
System.out.println("List created with new ArrayList<>(Arrays.asList()): " + fruitsList);
// Modify the list
System.out.println("Adding 'Fig' to the list");
fruitsList.add("Fig");
System.out.println("List after adding 'Fig': " + fruitsList);
System.out.println("Original array after List modification: " + Arrays.toString(fruitsArray));
// Method 3: Using Stream API (Java 8+)
System.out.println("\nMethod 3: Using Stream API");
List<String> fruitsListStream = Arrays.stream(fruitsArray)
.collect(Collectors.toList());
System.out.println("List created with Stream API: " + fruitsListStream);
// Modify the list
System.out.println("Adding 'Grape' to the list");
fruitsListStream.add("Grape");
System.out.println("List after adding 'Grape': " + fruitsListStream);
System.out.println("Original array after List modification: " + Arrays.toString(fruitsArray));
}
}
Compilez et exécutez le programme :
cd ~/project javac src/main/java/ArrayToListConversion.java java -cp src/main/java ArrayToListConversion
Vous devriez voir une sortie similaire à celle-ci :
Converting Arrays to Lists
=========================
Original array: [Apple, Banana, Cherry, Date, Elderberry]
Method 1: Arrays.asList()
List created with Arrays.asList(): [Apple, Banana, Cherry, Date, Elderberry]
Changing element at index 0 to 'Apricot'
List after change: [Apricot, Banana, Cherry, Date, Elderberry]
Original array after List change: [Apricot, Banana, Cherry, Date, Elderberry]
Trying to add a new element to the fixed-size list...
Error: Cannot add to fixed-size list!
Method 2: new ArrayList<>(Arrays.asList())
List created with new ArrayList<>(Arrays.asList()): [Apple, Banana, Cherry, Date, Elderberry]
Adding 'Fig' to the list
List after adding 'Fig': [Apple, Banana, Cherry, Date, Elderberry, Fig]
Original array after List modification: [Apple, Banana, Cherry, Date, Elderberry]
Method 3: Using Stream API
List created with Stream API: [Apple, Banana, Cherry, Date, Elderberry]
Adding 'Grape' to the list
List after adding 'Grape': [Apple, Banana, Cherry, Date, Elderberry, Grape]
Original array after List modification: [Apple, Banana, Cherry, Date, Elderberry]
Comprendre les différentes méthodes de conversion
Arrays.asList() :
- Crée une liste de taille fixe soutenue par le tableau d'origine.
- La taille de la liste ne peut pas être modifiée (pas d'ajout/suppression d'éléments).
- Les modifications apportées aux éléments de la liste affectent le tableau d'origine.
new ArrayList<>(Arrays.asList()) :
- Crée une nouvelle ArrayList qui contient tous les éléments du tableau.
- La liste est mutable (peut ajouter/supprimer des éléments).
- Les modifications apportées à la liste n'affectent pas le tableau d'origine.
Stream API (Java 8+) :
- Une approche plus moderne utilisant la programmation fonctionnelle.
- Crée une liste complètement indépendante.
- Offre la flexibilité d'effectuer des transformations pendant la conversion.
Pour les débutants, la deuxième méthode (new ArrayList<>(Arrays.asList())) est généralement la plus utile car elle crée une liste entièrement mutable sans affecter le tableau d'origine.
Travailler avec les tableaux de types primitifs
Dans les étapes précédentes, nous avons travaillé avec des tableaux de types de référence (String). Cependant, les tableaux Java peuvent également contenir des types primitifs tels que int, double, etc. La conversion des tableaux de types primitifs en listes nécessite des étapes supplémentaires car les génériques Java ne fonctionnent qu'avec des types de référence.
Créons un nouvel exemple pour illustrer ce processus.
Créer un nouveau fichier Java
Créez un nouveau fichier Java appelé
PrimitiveArrayToList.javadans le même répertoire :Depuis le WebIDE, accédez à
project/src/main/java, faites un clic droit et sélectionnez "New File". Nommez-lePrimitiveArrayToList.java.Ajoutez le code suivant au fichier :
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class PrimitiveArrayToList {
public static void main(String[] args) {
System.out.println("Converting Primitive Arrays to Lists");
System.out.println("===================================");
// Create a primitive int array
int[] numbersArray = {10, 20, 30, 40, 50};
System.out.println("Original primitive array: " + Arrays.toString(numbersArray));
// Method 1: Manual conversion
System.out.println("\nMethod 1: Manual conversion");
List<Integer> numbersList1 = new ArrayList<>();
for (int number : numbersArray) {
numbersList1.add(number); // Autoboxing converts int to Integer
}
System.out.println("List after manual conversion: " + numbersList1);
// Method 2: Using Java 8 Streams
System.out.println("\nMethod 2: Using Java 8 Streams");
List<Integer> numbersList2 = Arrays.stream(numbersArray)
.boxed() // Converts IntStream to Stream<Integer>
.collect(Collectors.toList());
System.out.println("List after stream conversion: " + numbersList2);
// Modify the lists to demonstrate independence from the array
System.out.println("\nModifying the lists:");
numbersList1.add(60);
numbersList1.set(0, 15);
numbersList2.add(70);
numbersList2.remove(0);
System.out.println("List 1 after modifications: " + numbersList1);
System.out.println("List 2 after modifications: " + numbersList2);
System.out.println("Original array after List modifications: " + Arrays.toString(numbersArray));
// Create and convert other primitive type arrays
System.out.println("\nOther primitive type examples:");
double[] doubleArray = {1.1, 2.2, 3.3, 4.4, 5.5};
List<Double> doubleList = Arrays.stream(doubleArray)
.boxed()
.collect(Collectors.toList());
System.out.println("Double array: " + Arrays.toString(doubleArray));
System.out.println("Double list: " + doubleList);
boolean[] boolArray = {true, false, true, true, false};
List<Boolean> boolList = new ArrayList<>();
for (boolean value : boolArray) {
boolList.add(value);
}
System.out.println("Boolean array: " + Arrays.toString(boolArray));
System.out.println("Boolean list: " + boolList);
}
}
Compilez et exécutez le programme :
cd ~/project javac src/main/java/PrimitiveArrayToList.java java -cp src/main/java PrimitiveArrayToList
Vous devriez voir une sortie similaire à celle-ci :
Converting Primitive Arrays to Lists
===================================
Original primitive array: [10, 20, 30, 40, 50]
Method 1: Manual conversion
List after manual conversion: [10, 20, 30, 40, 50]
Method 2: Using Java 8 Streams
List after stream conversion: [10, 20, 30, 40, 50]
Modifying the lists:
List 1 after modifications: [15, 20, 30, 40, 50, 60]
List 2 after modifications: [20, 30, 40, 50, 70]
Original array after List modifications: [10, 20, 30, 40, 50]
Other primitive type examples:
Double array: [1.1, 2.2, 3.3, 4.4, 5.5]
Double list: [1.1, 2.2, 3.3, 4.4, 5.5]
Boolean array: [true, false, true, true, false]
Boolean list: [true, false, true, true, false]
Comprendre la conversion des tableaux de types primitifs
Lorsque vous travaillez avec des tableaux de types primitifs, il y a deux considérations clés :
Autoboxing : Java convertit automatiquement les valeurs primitives en leurs objets de classe wrapper lors de l'ajout aux collections. Par exemple,
intest converti enInteger.Méthodes de boxing pour les Streams : Lorsque vous utilisez des streams avec des tableaux de types primitifs, vous devez appeler la méthode
.boxed()pour convertir les streams de types primitifs en streams d'objets.
Le processus de conversion crée des listes complètement nouvelles qui sont indépendantes des tableaux d'origine. Cela signifie que :
- La modification de la liste n'affectera pas le tableau d'origine.
- Les listes sont entièrement mutables (vous pouvez ajouter, supprimer ou modifier des éléments).
- Chaque élément de la liste est un nouvel objet (wrapper) qui contient la valeur du tableau.
Cette indépendance est particulièrement utile lorsque vous devez manipuler les données sans risquer de modifier le tableau d'origine.
Applications pratiques et pièges courants
Maintenant que nous comprenons comment convertir des tableaux en listes mutables, explorons quelques applications pratiques et pièges courants. Nous allons créer un dernier exemple qui démontre des cas d'utilisation réels et comment éviter les erreurs courantes.
Créer un nouveau fichier Java
Créez un nouveau fichier Java appelé
ArrayListPractical.javadans le même répertoire :Depuis le WebIDE, accédez à
project/src/main/java, faites un clic droit et sélectionnez "New File". Nommez-leArrayListPractical.java.Ajoutez le code suivant au fichier :
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
public class ArrayListPractical {
public static void main(String[] args) {
System.out.println("Practical Applications and Common Pitfalls");
System.out.println("========================================");
// Use case 1: Creating a mutable list from a configuration array
String[] defaultSettings = {"dark-mode", "auto-save", "notifications"};
System.out.println("Default settings array: " + Arrays.toString(defaultSettings));
// Create a mutable list of user settings starting with defaults
List<String> userSettings = new ArrayList<>(Arrays.asList(defaultSettings));
System.out.println("Initial user settings list: " + userSettings);
// User can add or remove settings
userSettings.add("sync-enabled");
userSettings.remove("notifications");
System.out.println("Modified user settings: " + userSettings);
System.out.println("Original default settings (unchanged): " + Arrays.toString(defaultSettings));
// Use case 2: Working with legacy APIs that return arrays
System.out.println("\nUse case: Working with legacy APIs");
// Simulate a legacy API that returns an array
String[] legacyData = getLegacyData();
System.out.println("Data from legacy API (array): " + Arrays.toString(legacyData));
// Convert to a mutable list for modern processing
List<String> modernData = new ArrayList<>(Arrays.asList(legacyData));
// Process with modern methods
modernData.removeIf(item -> item.startsWith("OLD_"));
modernData.replaceAll(item -> item.toLowerCase());
System.out.println("Processed data (list): " + modernData);
// Common Pitfall 1: Forgetting that Arrays.asList creates a fixed-size list
System.out.println("\nCommon Pitfall 1: Fixed-size list");
Integer[] numberArray = {1, 2, 3, 4, 5};
// This creates a fixed-size list
List<Integer> wrongWay = Arrays.asList(numberArray);
System.out.println("Fixed-size list: " + wrongWay);
try {
wrongWay.add(6); // This will fail
} catch (UnsupportedOperationException e) {
System.out.println("Error: Cannot add to fixed-size list!");
}
// Correct way
List<Integer> rightWay = new ArrayList<>(Arrays.asList(numberArray));
rightWay.add(6); // This works fine
System.out.println("Mutable list: " + rightWay);
// Common Pitfall 2: Array of primitives
System.out.println("\nCommon Pitfall 2: Array of primitives");
int[] primitiveArray = {10, 20, 30};
// This won't compile: Arrays.asList(primitiveArray)
// List<Integer> primitiveList = Arrays.asList(primitiveArray);
// Correct ways
List<Integer> primitiveList1 = new ArrayList<>();
for (int value : primitiveArray) {
primitiveList1.add(value);
}
List<Integer> primitiveList2 = Arrays.stream(primitiveArray)
.boxed()
.toList();
System.out.println("Primitive array: " + Arrays.toString(primitiveArray));
System.out.println("Converted list (loop method): " + primitiveList1);
System.out.println("Converted list (stream method): " + primitiveList2);
}
// Simulate a legacy API that returns an array
private static String[] getLegacyData() {
return new String[] {"OLD_RECORD1", "ACTIVE_DATA", "OLD_RECORD2", "CURRENT_INFO"};
}
}
Compilez et exécutez le programme :
cd ~/project javac src/main/java/ArrayListPractical.java java -cp src/main/java ArrayListPractical
Vous devriez voir une sortie similaire à celle-ci :
Practical Applications and Common Pitfalls
========================================
Default settings array: [dark-mode, auto-save, notifications]
Initial user settings list: [dark-mode, auto-save, notifications]
Modified user settings: [dark-mode, auto-save, sync-enabled]
Original default settings (unchanged): [dark-mode, auto-save, notifications]
Use case: Working with legacy APIs
Data from legacy API (array): [OLD_RECORD1, ACTIVE_DATA, OLD_RECORD2, CURRENT_INFO]
Processed data (list): [active_data, current_info]
Common Pitfall 1: Fixed-size list
Fixed-size list: [1, 2, 3, 4, 5]
Error: Cannot add to fixed-size list!
Mutable list: [1, 2, 3, 4, 5, 6]
Common Pitfall 2: Array of primitives
Primitive array: [10, 20, 30]
Converted list (loop method): [10, 20, 30]
Converted list (stream method): [10, 20, 30]
Principaux points à retenir des applications pratiques
Gestion de la configuration : L'utilisation de tableaux pour les paramètres par défaut et de listes pour les paramètres spécifiques à l'utilisateur permet une flexibilité tout en conservant les valeurs par défaut.
Travailler avec les API héritées : De nombreuses anciennes API Java renvoient des tableaux, que vous pouvez convertir en listes pour tirer parti des fonctionnalités Java modernes telles que les expressions lambda et les références de méthode.
Pièges courants à éviter :
- N'oubliez pas que
Arrays.asList()crée une liste de taille fixe qui ne peut pas croître ou rétrécir. - Les tableaux de types primitifs ne peuvent pas être directement passés à
Arrays.asList()- vous devez utiliser des boucles ou des streams avec du boxing.
- N'oubliez pas que
Meilleure pratique : Pour la plupart des cas d'utilisation, l'approche la plus sûre consiste à utiliser
new ArrayList<>(Arrays.asList(array))pour les tableaux d'objets et les méthodes de stream pour les tableaux de types primitifs.
En comprenant ces modèles et ces pièges, vous pouvez travailler efficacement avec les tableaux et les listes dans vos applications Java, en choisissant la bonne structure de données et la bonne méthode de conversion pour chaque situation.
Résumé
Dans ce lab, vous avez appris à créer des listes mutables à partir de tableaux Java tout en préservant les données du tableau d'origine. Vous avez exploré :
Les différences fondamentales entre les tableaux Java et les listes, y compris leur structure, leurs capacités et leurs cas d'utilisation.
Plusieurs méthodes pour convertir des tableaux en listes :
- Utilisation de
Arrays.asList()pour une vue de taille fixe du tableau. - Utilisation de
new ArrayList<>(Arrays.asList())pour une liste entièrement mutable. - Utilisation de l'API Stream avec
.boxed()pour les tableaux de types primitifs.
- Utilisation de
Considérations particulières pour les tableaux de types primitifs, qui nécessitent un boxing explicite pour être convertis en listes d'objets wrapper.
Applications pratiques et pièges courants lors de l'utilisation de tableaux et de listes, y compris la gestion de la configuration et l'interaction avec les API héritées.
Ces techniques sont précieuses dans de nombreuses applications Java réelles où vous devez travailler avec des tableaux et des listes, en particulier lorsque vous devez préserver les données d'origine tout en créant des collections flexibles et mutables pour la manipulation. Comprendre la relation entre les tableaux et les listes vous permet d'écrire du code Java plus efficace et maintenable.



