How to Implement Custom Serialization for Collections in Java?

How to Implement Custom Serialization for Collections in Java?

Introduction

In Java, serialization is a process of converting an object into a byte stream to save it to a file or send it over the network. By default, Java provides built-in serialization support using the Serializable interface. However, in some scenarios, you may want to implement custom serialization logic for collections (such as List, Set, or Map) to achieve more control over how objects are serialized and deserialized.

This article will guide you through the process of implementing custom serialization for collections in Java. We will cover the following:

  • What is serialization and why custom serialization is needed?
  • How to implement readObject() and writeObject() methods for collections
  • Working with List, Set, and Map collections
  • Examples of custom serialization

What is Serialization?

Serialization in Java is the process of converting an object into a byte stream. This allows an object to be stored in files or transmitted over the network, while still maintaining its state. When an object is serialized, the fields of the object are converted into a format that can be saved or sent.

In Java, any class that implements the Serializable interface can be serialized. By default, Java uses the standard mechanism to handle the process of serializing objects and their fields. However, in some situations, developers might need to customize the process to manage how data is serialized, especially for complex objects like collections.

Why Implement Custom Serialization for Collections?

Collections like List, Set, and Map can contain various types of objects, and sometimes the default serialization may not suffice. You might want to:

  • Exclude certain fields from serialization.
  • Encrypt or compress data before serializing it.
  • Handle circular references or complex nested objects.
  • Improve performance by customizing the serialization logic for large collections.

How to Implement Custom Serialization?

To implement custom serialization, Java provides two special methods in the Serializable interface:

  • private void writeObject(java.io.ObjectOutputStream out) throws IOException
  • private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException

These methods are used to control how an object is serialized and deserialized. The writeObject() method is responsible for writing the object’s state, while readObject() reads the object’s state during deserialization.

Custom Serialization with Collections Example

Let’s consider a List collection of Employee objects. We want to implement custom serialization to save only specific fields of the Employee class and exclude others.

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

class Employee implements Serializable {
    private String name;
    private int age;
    private transient String password; // Excluded from serialization

    public Employee(String name, int age, String password) {
        this.name = name;
        this.age = age;
        this.password = password;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();  // Write default fields
        out.writeObject(password);  // Manually serialize the password
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();  // Read default fields
        password = (String) in.readObject();  // Manually deserialize the password
    }

    @Override
    public String toString() {
        return "Employee{name='" + name + "', age=" + age + ", password='" + password + "'}";
    }
}

public class CustomSerializationExample {
    public static void main(String[] args) {
        List employees = new ArrayList<>();
        employees.add(new Employee("Alice", 30, "pass123"));
        employees.add(new Employee("Bob", 35, "pass456"));

        try {
            // Serialize the list
            FileOutputStream fileOut = new FileOutputStream("employees.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(employees);
            out.close();
            fileOut.close();

            // Deserialize the list
            FileInputStream fileIn = new FileInputStream("employees.ser");
            ObjectInputStream in = new ObjectInputStream(fileIn);
            List deserializedEmployees = (List) in.readObject();
            in.close();
            fileIn.close();

            // Output the deserialized list
            deserializedEmployees.forEach(System.out::println);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

In this example, we have used writeObject() and readObject() to manually serialize and deserialize the password field of the Employee class, which is marked as transient (meaning it is excluded from default serialization).

Custom Serialization with Set and Map Example

Similar to List, you can apply custom serialization to other collections like Set and Map. Here’s how you can serialize a HashSet and a HashMap:

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

class CustomSetSerialization {
    private Set customSet = new HashSet<>();

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeInt(customSet.size());  // Write the size of the set
        for (String s : customSet) {
            out.writeObject(s);  // Serialize each element
        }
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        int size = in.readInt();  // Read the set size
        customSet = new HashSet<>();
        for (int i = 0; i < size; i++) {
            customSet.add((String) in.readObject());  // Deserialize each element
        }
    }

    @Override
    public String toString() {
        return "CustomSetSerialization{customSet=" + customSet + "}";
    }
}

public class SetSerializationExample {
    public static void main(String[] args) {
        CustomSetSerialization customSetSerialization = new CustomSetSerialization();
        customSetSerialization.customSet.add("Java");
        customSetSerialization.customSet.add("Python");

        try {
            // Serialize the custom set
            FileOutputStream fileOut = new FileOutputStream("setSerialization.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(customSetSerialization);
            out.close();
            fileOut.close();

            // Deserialize the custom set
            FileInputStream fileIn = new FileInputStream("setSerialization.ser");
            ObjectInputStream in = new ObjectInputStream(fileIn);
            CustomSetSerialization deserializedSet = (CustomSetSerialization) in.readObject();
            in.close();
            fileIn.close();

            System.out.println(deserializedSet);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Conclusion

Custom serialization gives you the flexibility to handle how collections are serialized in Java. By overriding the writeObject() and readObject() methods, you can control the serialization of complex data structures. This technique is particularly useful when working with collections containing objects that require special handling, such as encryption, compression, or exclusion from serialization.

© 2025 Tech Interview Guide. All rights reserved.

Please follow and like us:

Leave a Comment