CodeGym /Cursos /JAVA 25 SELF /Serialização de coleções: List, Map, Set

Serialização de coleções: List, Map, Set

JAVA 25 SELF
Nível 42 , Lição 4
Disponível

1. Serialização de coleções

Boa notícia: quase todas as coleções padrão do Java (por exemplo, ArrayList, HashSet, HashMap e suas “amigas”) já implementam Serializable. Isso significa que você pode serializá-las prontas para uso, sem malabarismos complicados.

Exemplo:

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

public class MyList extends ArrayList<String> implements Serializable {
    // Você pode nem escrever nada — ArrayList já é Serializable!
}

Na prática, você geralmente serializa coleções padrão, e tudo funciona sem complicações extras.

Como serializar uma coleção?

Para serializar uma coleção, usa-se a mesma abordagem que para qualquer outro objeto:

  • Crie a coleção.
  • Grave-a em um arquivo via ObjectOutputStream.
  • Leia de volta via ObjectInputStream.

Exemplo 1: Serialização ArrayList<String>

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

public class SerializeListDemo {
    public static void main(String[] args) throws Exception {
        // 1. Criamos uma lista de strings
        List<String> books = new ArrayList<>();
        books.add("O Apanhador no Campo de Centeio");
        books.add("Grandes Esperanças");
        books.add("A Divina Comédia");

        // 2. Salvamos a lista em um arquivo
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("books.ser"));
        out.writeObject(books);
        out.close();

        // 3. Lemos a lista de volta do arquivo
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("books.ser"));
        List<String> loadedBooks = (List<String>) in.readObject();
        in.close();

        // 4. Verificamos o resultado
        System.out.println("Lista de livros após a desserialização:");
        for (String book : loadedBooks) {
            System.out.println("- " + book);
        }
    }
}

Saída:

Lista de livros após a desserialização:
- O Apanhador no Campo de Centeio
- Grandes Esperanças
- A Divina Comédia

Exemplo 2: Serialização de 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("Conjunto após a desserialização: " + loadedNumbers);

Exemplo 3: Serialização de 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("Mapa após a desserialização: " + loadedScores);

Pontos importantes

A ordem é preservada?

  • Para List (por exemplo, ArrayList) a ordem dos elementos é sempre preservada.
  • Para Set (HashSet) a ordem não é garantida (tanto antes quanto depois da serialização).
  • Para Map (HashMap) a ordem dos pares chave-valor não é garantida (se precisar de ordem — use LinkedHashMap).

Coleções vazias se serializam e desserializam sem problemas. Após a desserialização, você obterá uma lista/conjunto/mapa vazio.

Coleções aninhadas (por exemplo, List<List<String>>) são serializadas corretamente se todos os elementos aninhados forem serializáveis.

2. Requisitos para os elementos da coleção

É aqui que costuma estar a primeira armadilha séria!

Todos os elementos da coleção também devem ser serializáveis.

Se pelo menos um elemento da coleção não implementa a interface Serializable, a serialização da coleção terminará com o erro NotSerializableException. E, se a coleção for grande e o erro estiver em algum lugar lá dentro, encontrar o culpado vira uma caça ao tesouro.

Exemplo: serializando uma coleção com um objeto não serializável

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)); // <- Opa!

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("badlist.ser"));
        try {
            out.writeObject(list); // Uma exceção será lançada aqui!
        } catch (NotSerializableException e) {
            System.out.println("Erro de serialização: " + e);
        }
        out.close();
    }
}

Resultado:

Erro de serialização: java.io.NotSerializableException: NotSerializableClass

O que fazer?

A solução é simples: todos os elementos da coleção devem ser tipos padrão, como String ou Integer, ou suas próprias classes que implementem a interface Serializable. Se alguma classe não for serializável, basta adicionar a ela implements Serializable, e o problema estará resolvido.

3. Particularidades da serialização de diferentes coleções

A ordem dos elementos é preservada?

  • List: Sim, a ordem dos elementos é preservada.
  • Set: Depende da implementação. Em HashSet a ordem não é garantida, já em LinkedHashSet — é preservada.
  • Map: Em HashMap a ordem não é garantida, em LinkedHashMap — é preservada a ordem de inserção.

Demonstração:

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); // sempre [A, B, C]
System.out.println("Set: " + loadedSet);   // pode ser [A, C, B] etc.

Serialização de coleções vazias

Coleções vazias são serializadas sem problemas. Após a desserialização, você obterá um objeto vazio do tipo necessário.

Serialização de coleções aninhadas

É possível serializar coleções que contêm outras coleções:

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

// Serialização
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("table.ser"));
out.writeObject(table);
out.close();

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

System.out.println(loadedTable);

4. Exemplo prático: serializando uma coleção de objetos de uma classe própria

Vamos escrever juntos um pequeno aplicativo para uma “biblioteca virtual”, em que vamos serializar uma lista de livros. A classe Book deve ser serializável!

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

class Book implements Serializable {
    private static final long serialVersionUID = 1L; // para compatibilidade entre versões da classe
    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("O Apanhador no Campo de Centeio", "J. D. Salinger", 1951));
        books.add(new Book("Grandes Esperanças", "Charles Dickens", 1861));
        books.add(new Book("A Divina Comédia", "Dante Alighieri", 1320));

        // Salvamos a lista em um arquivo
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("mylibrary.ser"));
        out.writeObject(books);
        out.close();

        // Lemos a lista de volta
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("mylibrary.ser"));
        List<Book> loadedBooks = (List<Book>) in.readObject();
        in.close();

        System.out.println("Livros do arquivo:");
        for (Book b : loadedBooks) {
            System.out.println("- " + b);
        }
    }
}

5. Erros comuns ao serializar coleções

Erro nº 1: NotSerializableException em um elemento da coleção. Se pelo menos um elemento da coleção não for serializável, a serialização “vai falhar” com o erro NotSerializableException. Por exemplo, se você acidentalmente adicionou à coleção um objeto que não implementa Serializable ou se esqueceu de adicionar essa interface à sua classe.

Erro nº 2: Alterar a classe entre a serialização e a desserialização. Se você serializou uma coleção de objetos e depois mudou a estrutura da classe (por exemplo, adicionou ou removeu campos), durante a desserialização pode ocorrer a exceção InvalidClassException. Para evitar isso, use o campo serialVersionUID na classe.

Erro nº 3: Serializar uma coleção com campos transient ou static. Campos marcados como transient ou static não são serializados. Se seus objetos dependem desses campos, após a desserialização eles terão valores padrão (por exemplo, null ou 0).

Erro nº 4: Serializar coleções com objetos aninhados não serializáveis. Se na coleção houver coleções aninhadas ou objetos que não implementam Serializable, o erro surgirá no nível mais profundo — nem sempre fica claro onde procurar o problema. Verifique todos os níveis de aninhamento!

Erro nº 5: Desempenho com coleções grandes. Se a coleção for muito grande, a serialização pode levar muito tempo e ocupar muito espaço em disco. Nesses casos, considere a serialização em fluxo (streaming) ou a divisão da coleção em partes.

1
Pesquisa/teste
Serialização, nível 42, lição 4
Indisponível
Serialização
Introdução à serialização de objetos
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION