CodeGym /Kurse /JAVA 25 SELF /Serialisierung von Collections: List, Map, Set

Serialisierung von Collections: List, Map, Set

JAVA 25 SELF
Level 42 , Lektion 4
Verfügbar

1. Serialisierung von Collections

Gute Nachricht: Fast alle Standard-Collections in Java (z. B. ArrayList, HashSet, HashMap und ihre Freunde) implementieren bereits Serializable. Das bedeutet, dass Sie sie out of the box serialisieren können, ohne komplizierte Verrenkungen.

Beispiel:

import java.io.Serializable;
import java.util.ArrayList;

public class MyList extends ArrayList<String> implements Serializable {
    // Man kann sogar gar nichts schreiben — ArrayList ist bereits Serializable!
}

In der Praxis serialisieren Sie üblicherweise Standard-Collections, und alles funktioniert ohne zusätzlichen Aufwand.

Wie serialisiert man eine Collection?

Für die Serialisierung einer Collection wird derselbe Ansatz verwendet wie für jedes andere Objekt:

  • Collection erstellen.
  • Sie über ObjectOutputStream in eine Datei schreiben.
  • Über ObjectInputStream wieder einlesen.

Beispiel 1: Serialisierung ArrayList<String>

import java.io.*;
import java.util.*;

public class SerializeListDemo {
    public static void main(String[] args) throws Exception {
        // 1. Wir erstellen eine String-Liste
        List<String> books = new ArrayList<>();
        books.add("Der Fänger im Roggen");
        books.add("Große Erwartungen");
        books.add("Die Göttliche Komödie");

        // 2. Wir speichern die Liste in eine Datei
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("books.ser"));
        out.writeObject(books);
        out.close();

        // 3. Wir lesen die Liste wieder aus der Datei
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("books.ser"));
        List<String> loadedBooks = (List<String>) in.readObject();
        in.close();

        // 4. Wir prüfen das Ergebnis
        System.out.println("Liste der Bücher nach der Deserialisierung:");
        for (String book : loadedBooks) {
            System.out.println("- " + book);
        }
    }
}

Ausgabe:

Liste der Bücher nach der Deserialisierung:
- Der Fänger im Roggen
- Große Erwartungen
- Die Göttliche Komödie

Beispiel 2: Serialisierung HashSet<Integer>

Set<Integer> numbers = new HashSet<>(Arrays.asList(10, 20, 30, 40));
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("numbers.ser"));
out.writeObject(numbers);
out.close();

ObjectInputStream in = new ObjectInputStream(new FileInputStream("numbers.ser"));
Set<Integer> loadedNumbers = (Set<Integer>) in.readObject();
in.close();

System.out.println("Menge nach der Deserialisierung: " + loadedNumbers);

Beispiel 3: Serialisierung HashMap<String, Integer>

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 100);
scores.put("Bob", 80);

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("scores.ser"));
out.writeObject(scores);
out.close();

ObjectInputStream in = new ObjectInputStream(new FileInputStream("scores.ser"));
Map<String, Integer> loadedScores = (Map<String, Integer>) in.readObject();
in.close();

System.out.println("Map nach der Deserialisierung: " + loadedScores);

Wichtige Punkte

Bleibt die Reihenfolge erhalten?

  • Für List (z. B. ArrayList) bleibt die Reihenfolge der Elemente immer erhalten.
  • Für Set (HashSet) wird die Reihenfolge nicht garantiert (sowohl vor als auch nach der Serialisierung).
  • Für Map (HashMap) ist die Reihenfolge der Schlüssel-Wert-Paare nicht garantiert (wenn Sie eine Reihenfolge benötigen — verwenden Sie LinkedHashMap).

Leere Collections werden ohne Probleme serialisiert und deserialisiert. Nach der Deserialisierung erhalten Sie eine leere Liste/Menge/Map.

Verschachtelte Collections (z. B. List<List<String>>) werden korrekt serialisiert, sofern alle verschachtelten Elemente serialisierbar sind.

2. Anforderungen an die Elemente einer Collection

Hier lauert oft die erste ernsthafte Falle!

Alle Elemente der Collection müssen ebenfalls serialisierbar sein.

Wenn nur ein einziges Element der Collection das Interface Serializable nicht implementiert, endet die Serialisierung der Collection mit dem Fehler NotSerializableException. Und wenn die Collection groß ist und der Fehler irgendwo im Inneren steckt, wird die Suche nach dem Übeltäter schnell zur mühsamen Fehlersuche.

Beispiel: Serialisierung einer Collection mit einem nicht serialisierbaren Objekt

import java.io.*;
import java.util.*;

class NotSerializableClass {
    int value;
    public NotSerializableClass(int value) { 
        this.value = value; 
    }
}

public class NotSerializableDemo {
    public static void main(String[] args) throws Exception {
        List<Object> list = new ArrayList<>();
        list.add("Hello");
        list.add(new NotSerializableClass(123)); // <- Hoppla!

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("badlist.ser"));
        try {
            out.writeObject(list); // Hier wird eine Exception ausgelöst!
        } catch (NotSerializableException e) {
            System.out.println("Serialisierungsfehler: " + e);
        }
        out.close();
    }
}

Ergebnis:

Serialisierungsfehler: java.io.NotSerializableException: NotSerializableClass

Was tun?

Die Lösung ist einfach: Alle Elemente der Collection sollten entweder Standardtypen wie String oder Integer sein oder Ihre eigenen Klassen, die das Interface Serializable implementieren. Wenn eine Klasse nicht serialisierbar ist, genügt es, ihr implements Serializable hinzuzufügen, und das Problem ist behoben.

3. Besonderheiten der Serialisierung verschiedener Collections

Bleibt die Reihenfolge der Elemente erhalten?

  • List: Ja, die Reihenfolge der Elemente bleibt erhalten.
  • Set: Hängt von der Implementierung ab. In HashSet ist die Reihenfolge nicht garantiert, in LinkedHashSet hingegen bleibt sie erhalten.
  • Map: In HashMap ist die Reihenfolge nicht garantiert, in LinkedHashMap bleibt die Einfüge-Reihenfolge erhalten.

Demonstration:

List<String> list = Arrays.asList("A", "B", "C");
Set<String> set = new HashSet<>(list);

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("coll.ser"));
out.writeObject(list);
out.writeObject(set);
out.close();

ObjectInputStream in = new ObjectInputStream(new FileInputStream("coll.ser"));
List<String> loadedList = (List<String>) in.readObject();
Set<String> loadedSet = (Set<String>) in.readObject();
in.close();

System.out.println("List: " + loadedList); // immer [A, B, C]
System.out.println("Set: " + loadedSet);   // kann [A, C, B] usw. sein

Serialisierung leerer Collections

Leere Collections werden ohne Probleme serialisiert. Nach der Deserialisierung erhalten Sie ein leeres Objekt des gewünschten Typs.

Serialisierung verschachtelter Collections

Sie können Collections serialisieren, die andere Collections enthalten:

List<List<String>> table = new ArrayList<>();
table.add(Arrays.asList("row1-col1", "row1-col2"));
table.add(Arrays.asList("row2-col1", "row2-col2"));

// Serialisierung
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("table.ser"));
out.writeObject(table);
out.close();

// Deserialisierung
ObjectInputStream in = new ObjectInputStream(new FileInputStream("table.ser"));
List<List<String>> loadedTable = (List<List<String>>) in.readObject();
in.close();

System.out.println(loadedTable);

4. Praxisbeispiel: Serialisierung einer Collection von Objekten einer eigenen Klasse

Schreiben wir gemeinsam eine kleine Anwendung für eine „virtuelle Bibliothek“, in der wir eine Bücherliste serialisieren. Die Klasse Book muss serialisierbar sein!

import java.io.*;
import java.util.*;

class Book implements Serializable {
    private static final long serialVersionUID = 1L; // für die Kompatibilität von Klassenversionen
    String title;
    String author;
    int year;

    public Book(String title, String author, int year) {
        this.title = title;
        this.author = author;
        this.year = year;
    }

    @Override
    public String toString() {
        return title + " (" + author + ", " + year + ")";
    }
}

public class LibraryApp {
    public static void main(String[] args) throws Exception {
        List<Book> books = new ArrayList<>();
        books.add(new Book("Der Fänger im Roggen", "J. D. Salinger", 1951));
        books.add(new Book("Große Erwartungen", "Charles Dickens", 1861));
        books.add(new Book("Die Göttliche Komödie", "Dante Alighieri", 1320));

        // Wir speichern die Liste in eine Datei
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("mylibrary.ser"));
        out.writeObject(books);
        out.close();

        // Wir lesen die Liste wieder ein
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("mylibrary.ser"));
        List<Book> loadedBooks = (List<Book>) in.readObject();
        in.close();

        System.out.println("Bücher aus der Datei:");
        for (Book b : loadedBooks) {
            System.out.println("- " + b);
        }
    }
}

5. Typische Fehler bei der Serialisierung von Collections

Fehler Nr. 1: NotSerializableException bei einem Collection-Element. Wenn auch nur ein Element der Collection nicht serialisierbar ist, „scheitert“ die Serialisierung mit NotSerializableException. Zum Beispiel, wenn Sie versehentlich ein Objekt zur Collection hinzugefügt haben, das Serializable nicht implementiert, oder vergessen haben, dieses Interface Ihrer Klasse hinzuzufügen.

Fehler Nr. 2: Änderung der Klasse zwischen Serialisierung und Deserialisierung. Wenn Sie eine Collection von Objekten serialisiert haben und anschließend die Klassenstruktur ändern (z. B. Felder hinzufügen oder löschen), kann bei der Deserialisierung eine InvalidClassException auftreten. Verwenden Sie zur Vermeidung das Feld serialVersionUID in der Klasse.

Fehler Nr. 3: Serialisierung von Collections mit transient- oder static-Feldern. Felder, die als transient oder static markiert sind, werden nicht serialisiert. Wenn Ihre Objekte von solchen Feldern abhängen, haben sie nach der Deserialisierung Standardwerte (z. B. null oder 0).

Fehler Nr. 4: Serialisierung von Collections mit verschachtelten nicht serialisierbaren Objekten. Wenn es in der Collection verschachtelte Collections oder Objekte gibt, die Serializable nicht implementieren, tritt der Fehler auf der tiefsten Ebene auf — es ist nicht immer sofort klar, wo das Problem liegt. Prüfen Sie alle Verschachtelungsebenen!

Fehler Nr. 5: Leistung bei großen Collections. Wenn die Collection sehr groß ist, kann die Serialisierung viel Zeit und Speicherplatz beanspruchen. In solchen Fällen sollten Sie über Streaming-Serialisierung oder eine Aufteilung der Collection in Teile nachdenken.

1
Aufgabe
JAVA 25 SELF, Level 42, Lektion 4
Gesperrt
Serialisierung einer Liste von Strings
Serialisierung einer Liste von Strings
1
Aufgabe
JAVA 25 SELF, Level 42, Lektion 4
Gesperrt
Serialisierung einer Map mit Noten
Serialisierung einer Map mit Noten
1
Umfrage/Quiz
Serialisierung, Level 42, Lektion 4
Nicht verfügbar
Serialisierung
Einführung in die Serialisierung von Objekten
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION