Wie man eine veränderliche Liste aus einem Java-Array erstellt, ohne das ursprüngliche Array zu beeinflussen

JavaJavaBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In der Java-Programmierung ist die Arbeit mit verschiedenen Datenstrukturen für eine effiziente Programmentwicklung unerlässlich. Arrays und Listen sind zwei grundlegende Datenstrukturen, die unterschiedlichen Zwecken dienen. Während Arrays eine Speicher mit fester Größe bieten, bieten Listen Flexibilität mit dynamischer Größenanpassung und zusätzlichen Hilfsmethoden.

Dieses Tutorial konzentriert sich auf die Konvertierung von Java-Arrays in veränderbare Listen, ohne die ursprünglichen Array-Daten zu verändern. Am Ende dieses Labors werden Sie die Beziehung zwischen Arrays und Listen verstehen und praktische Techniken zur Konvertierung zwischen ihnen erlernen, während die Datenintegrität erhalten bleibt.

Java Arrays und Listen verstehen

In diesem Schritt werden wir die grundlegenden Unterschiede zwischen Java Arrays und Listen untersuchen, indem wir Beispiele für beides erstellen. Wir werden auch untersuchen, wie man auf ihre Elemente zugreift und sie anzeigt.

Erstellen eines Java-Projekts

Beginnen wir mit der Erstellung einer einfachen Java-Datei, mit der wir arbeiten können:

  1. Öffnen Sie das Terminal und navigieren Sie zum Projektverzeichnis:

    cd ~/project
  2. Erstellen Sie ein neues Verzeichnis für unsere Java-Dateien:

    mkdir -p src/main/java
    cd src/main/java
  3. Erstellen Sie eine neue Java-Datei namens ArrayListDemo.java mit der WebIDE. Klicken Sie auf das Explorer-Symbol in der WebIDE, navigieren Sie zu project/src/main/java, klicken Sie mit der rechten Maustaste und wählen Sie "New File". Nennen Sie sie ArrayListDemo.java.

  4. Fügen Sie der Datei den folgenden Code hinzu:

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);
    }
}
  1. Kompilieren und führen Sie das Java-Programm aus:
    cd ~/project
    javac src/main/java/ArrayListDemo.java
    java -cp src/main/java ArrayListDemo

Sie sollten eine Ausgabe ähnlich dieser sehen:

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]

Hauptunterschiede zwischen Arrays und Listen

  1. Größenflexibilität:

    • Arrays haben eine feste Größe, die nach der Erstellung nicht mehr geändert werden kann
    • Listen können bei Bedarf dynamisch wachsen oder schrumpfen
  2. Verfügbare Operationen:

    • Arrays haben eine begrenzte eingebaute Funktionalität
    • Listen bieten zahlreiche Methoden zum Hinzufügen, Entfernen und Bearbeiten von Elementen
  3. Typbeschränkungen:

    • Arrays können primitive Datentypen oder Objekte speichern
    • Listen können nur Objekte speichern (aber Autoboxing ermöglicht das indirekte Speichern von primitiven Datentypen)

Das Verständnis dieser Unterschiede hilft Ihnen, die richtige Datenstruktur für Ihre spezifischen Anforderungen auszuwählen.

Konvertieren von Arrays in Listen

Nachdem wir die Grundlagen von Arrays und Listen verstanden haben, wollen wir verschiedene Möglichkeiten zur Konvertierung eines Arrays in eine Liste untersuchen. Wir konzentrieren uns insbesondere auf die Erstellung veränderlicher Listen aus Arrays.

Erstellen einer neuen Java-Datei

  1. Erstellen Sie eine neue Java-Datei namens ArrayToListConversion.java im selben Verzeichnis:

    Navigieren Sie in der WebIDE zu project/src/main/java, klicken Sie mit der rechten Maustaste und wählen Sie "New File". Nennen Sie sie ArrayToListConversion.java.

  2. Fügen Sie der Datei den folgenden Code hinzu:

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));
    }
}
  1. Kompilieren und führen Sie das Programm aus:
    cd ~/project
    javac src/main/java/ArrayToListConversion.java
    java -cp src/main/java ArrayToListConversion

Sie sollten eine Ausgabe ähnlich dieser sehen:

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]

Verständnis der verschiedenen Konvertierungsmethoden

  1. Arrays.asList():

    • Erstellt eine Liste fester Größe, die vom ursprünglichen Array unterstützt wird
    • Die Listengröße kann nicht geändert werden (kein Hinzufügen/Entfernen von Elementen)
    • Änderungen an den Listenelementen wirken sich auf das ursprüngliche Array aus
  2. new ArrayList<>(Arrays.asList()):

    • Erstellt eine neue ArrayList, die alle Elemente aus dem Array enthält
    • Die Liste ist veränderlich (kann Elemente hinzufügen/entfernen)
    • Änderungen an der Liste wirken sich nicht auf das ursprüngliche Array aus
  3. Stream API (Java 8+):

    • Ein modernerer Ansatz unter Verwendung der funktionalen Programmierung
    • Erstellt eine völlig unabhängige Liste
    • Bietet Flexibilität bei der Durchführung von Transformationen während der Konvertierung

Für Anfänger ist die zweite Methode (new ArrayList<>(Arrays.asList())) im Allgemeinen am nützlichsten, da sie eine vollständig veränderliche Liste erstellt, ohne das ursprüngliche Array zu beeinflussen.

Arbeiten mit primitiven Arrays

In den vorherigen Schritten haben wir mit Arrays von Referenztypen (String) gearbeitet. Java-Arrays können jedoch auch primitive Typen wie int, double usw. enthalten. Die Konvertierung von primitiven Arrays in Listen erfordert zusätzliche Schritte, da Java-Generics nur mit Referenztypen funktionieren.

Lassen Sie uns ein neues Beispiel erstellen, um diesen Prozess zu demonstrieren.

Erstellen einer neuen Java-Datei

  1. Erstellen Sie eine neue Java-Datei namens PrimitiveArrayToList.java im selben Verzeichnis:

    Navigieren Sie in der WebIDE zu project/src/main/java, klicken Sie mit der rechten Maustaste und wählen Sie "New File". Nennen Sie sie PrimitiveArrayToList.java.

  2. Fügen Sie der Datei den folgenden Code hinzu:

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);
    }
}
  1. Kompilieren und führen Sie das Programm aus:
    cd ~/project
    javac src/main/java/PrimitiveArrayToList.java
    java -cp src/main/java PrimitiveArrayToList

Sie sollten eine Ausgabe ähnlich dieser sehen:

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]

Verständnis der Konvertierung primitiver Arrays

Bei der Arbeit mit primitiven Arrays sind zwei wichtige Aspekte zu berücksichtigen:

  1. Autoboxing: Java konvertiert primitive Werte automatisch in ihre Wrapper-Klassenobjekte, wenn sie zu Sammlungen hinzugefügt werden. Zum Beispiel wird int in Integer konvertiert.

  2. Boxing-Methoden für Streams: Bei der Verwendung von Streams mit primitiven Arrays müssen Sie die Methode .boxed() aufrufen, um primitive Streams in Objekt-Streams zu konvertieren.

Der Konvertierungsprozess erstellt völlig neue Listen, die unabhängig von den ursprünglichen Arrays sind. Das bedeutet:

  1. Das Ändern der Liste hat keine Auswirkungen auf das ursprüngliche Array
  2. Die Listen sind vollständig veränderlich (Sie können Elemente hinzufügen, entfernen oder ändern)
  3. Jedes Element in der Liste ist ein neues Objekt (Wrapper), das den Wert aus dem Array enthält

Diese Unabhängigkeit ist besonders nützlich, wenn Sie die Daten manipulieren müssen, ohne Änderungen am ursprünglichen Array zu riskieren.

Praktische Anwendungen und häufige Fallstricke

Nachdem wir verstanden haben, wie man Arrays in veränderliche Listen konvertiert, wollen wir einige praktische Anwendungen und häufige Fallstricke untersuchen. Wir erstellen ein abschließendes Beispiel, das reale Anwendungsfälle demonstriert und zeigt, wie man häufige Fehler vermeidet.

Erstellen einer neuen Java-Datei

  1. Erstellen Sie eine neue Java-Datei namens ArrayListPractical.java im selben Verzeichnis:

    Navigieren Sie in der WebIDE zu project/src/main/java, klicken Sie mit der rechten Maustaste und wählen Sie "New File". Nennen Sie sie ArrayListPractical.java.

  2. Fügen Sie der Datei den folgenden Code hinzu:

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"};
    }
}
  1. Kompilieren und führen Sie das Programm aus:
    cd ~/project
    javac src/main/java/ArrayListPractical.java
    java -cp src/main/java ArrayListPractical

Sie sollten eine Ausgabe ähnlich dieser sehen:

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]

Wichtige Erkenntnisse aus praktischen Anwendungen

  1. Konfigurationsmanagement: Die Verwendung von Arrays für Standardeinstellungen und Listen für benutzerspezifische Einstellungen ermöglicht Flexibilität bei gleichzeitiger Beibehaltung der Standardwerte.

  2. Arbeiten mit Legacy-APIs: Viele ältere Java-APIs geben Arrays zurück, die Sie in Listen konvertieren können, um moderne Java-Funktionen wie Lambda-Ausdrücke und Methodenreferenzen zu nutzen.

  3. Häufige Fallstricke, die es zu vermeiden gilt:

    • Denken Sie daran, dass Arrays.asList() eine Liste fester Größe erstellt, die nicht vergrößert oder verkleinert werden kann.
    • Primitive Arrays können nicht direkt an Arrays.asList() übergeben werden – Sie müssen Schleifen oder Streams mit Boxing verwenden.
  4. Best Practice: Für die meisten Anwendungsfälle ist der sicherste Ansatz die Verwendung von new ArrayList<>(Arrays.asList(array)) für Objekt-Arrays und Stream-Methoden für primitive Arrays.

Indem Sie diese Muster und Fallstricke verstehen, können Sie in Ihren Java-Anwendungen effektiv mit Arrays und Listen arbeiten und für jede Situation die richtige Datenstruktur und Konvertierungsmethode auswählen.

Zusammenfassung

In diesem Lab haben Sie gelernt, wie man veränderliche Listen aus Java-Arrays erstellt und dabei die ursprünglichen Array-Daten beibehält. Sie haben Folgendes untersucht:

  1. Die grundlegenden Unterschiede zwischen Java-Arrays und Listen, einschließlich ihrer Struktur, Fähigkeiten und Anwendungsfälle.

  2. Mehrere Methoden zur Konvertierung von Arrays in Listen:

    • Verwendung von Arrays.asList() für eine Ansicht fester Größe des Arrays
    • Verwendung von new ArrayList<>(Arrays.asList()) für eine vollständig veränderliche Liste
    • Verwendung der Stream-API mit .boxed() für primitive Arrays
  3. Besondere Überlegungen für primitive Arrays, die explizites Boxing erfordern, um in Listen von Wrapper-Objekten konvertiert zu werden.

  4. Praktische Anwendungen und häufige Fallstricke bei der Arbeit mit Arrays und Listen, einschließlich Konfigurationsmanagement und der Interaktion mit Legacy-APIs.

Diese Techniken sind in vielen realen Java-Anwendungen wertvoll, in denen Sie sowohl mit Arrays als auch mit Listen arbeiten müssen, insbesondere wenn Sie Originaldaten beibehalten und gleichzeitig flexible, veränderliche Sammlungen zur Manipulation erstellen müssen. Das Verständnis der Beziehung zwischen Arrays und Listen ermöglicht es Ihnen, effizienteren, wartungsfreundlicheren Java-Code zu schreiben.