eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

When developing software, it’s often necessary to write an object in memory to a file and, conversely, to read file contents into an object. This is simple to do with primitive and String values but becomes more complicated when dealing with data structures and objects.

One common Java data structure is the HashMap. In this tutorial, we’ll cover three methods for reading and writing files with HashMap data: Java Properties, Java object serialization, and JSON serialization using third-party libraries.

2. Using the Java Properties Class

A common application of a map is a properties file, which contains key-value pairs of Strings representing application configuration. The Java Properties class is well-suited to working with String-based HashMaps. For example, let’s create a map of student data:

Map<String, String> studentData = new HashMap<>();
studentData.put("student.firstName", "Henry");
studentData.put("student.lastName", "Winter");

The Properties class implements Map<Object, Object>, so it’s easy to read in all values from a HashMap:

Properties props = new Properties();
props.putAll(studentData);

We can create a temporary file and use the store method to write the Properties object to the file:

File file = File.createTempFile("student", ".data");
try (OutputStream output = Files.newOutputStream(file.toPath())) {
    props.store(output, null);
}

This method takes an OutputStream (or Writer) and an optional String for adding comments to the file. Here, we can pass in null. If we view the file we created, we can see our student data:

student.firstName: Henry
student.lastName: Winter

To read the file content back into a Properties object, we can use the load method:

Properties propsFromFile = new Properties();
try (InputStream input = Files.newInputStream(file.toPath())) {
    propsFromFile.load(input);
}

Since Properties implements Map<Object, Object> (but contains only String keys and values), we can get our original map back by streaming stringPropertyNames and collecting the results back into a map:

HashMap<String, String> studentDataFromProps = propsFromFile.stringPropertyNames()
  .stream()
  .collect(Collectors.toMap(key -> key, props::getProperty));
assertThat(studentDataFromProps).isEqualTo(studentData);

Using Properties is straightforward, but only if we’re dealing with a HashMap that has String keys and values. For any other mapping, we’ll need to use another strategy.

3. Working with Object Serialization

Java provides Serializable, an interface for converting objects to and from a byte stream. Let’s define a custom class, Student, that contains student data. We’ll have it implement Serializable (and set a serialVersionUID as recommended in the documentation):

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private String firstName;
    private String lastName;

    // Standard getters, setters, equals and hashCode methods
}

Next, we’ll create a mapping of student ID to a Student instance:

Map<Integer, Student> studentData = new HashMap<>();
studentData.put(1234, new Student("Henry", "Winter"));
studentData.put(5678, new Student("Richard", "Papen"));

Then, we can use an ObjectOutputStream to write the HashMap to a file:

File file = File.createTempFile("student", ".data");
try (FileOutputStream fileOutput = new FileOutputStream(file); 
  ObjectOutputStream objectStream = new  ObjectOutputStream(fileOutput)) {
    objectStream.writeObject(studentData);
}

This file will contain binary data and is not human-readable. To verify our file is correct, we can read it back into a HashMap using an ObjectInputStream:

Map<Integer, Student> studentsFromFile;
try (FileInputStream fileReader = new FileInputStream(file);
  ObjectInputStream objectStream = new ObjectInputStream(fileReader)) {
    studentsFromFile = (HashMap<Integer, Student>) objectStream.readObject();
}
assertThat(studentsFromFile).isEqualTo(studentData);

Note that we had to cast the result of readObject back to a HashMap<Integer, Student>. We ignore the unchecked cast warning here since the file will only ever contain our HashMap, but type safety should be considered for operational code.

Serializable provides a relatively simple way to serialize and deserialize a HashMap from a file, but it may not always be possible to serialize a class in this way – particularly if we’re dealing with a class that we can’t modify. Luckily, there is still another option.

4. Using JSON Libraries

JSON is a widely-used format for specifying key-value pairs of data. There are several open-source libraries available for working with JSON in Java. One advantage of JSON is that it’s human-readable – a JSON representation of our map of student data from above looks like this:

{
    1234: {
        "firstName": "Henry",
        "lastName": "Winter"
    },
    5678: {
        "firstName": "Richard",
        "lastName": "Papen"
    }
}

Here, we’ll use two of the most well-known libraries, Jackson and Gson, to convert our HashMap to and from a JSON file.

4.1. Jackson

Jackson is a common option for JSON serialization in Java. We’ll only cover the basics necessary to serialize our simple data structure – for more information, see our Jackson tutorials.

Using the same map of student data above, we can create a Jackson ObjectMapper and use it to write our HashMap as JSON to a file:

ObjectMapper mapper = new ObjectMapper();
File file = File.createTempFile("student", ".data");
try (FileOutputStream fileOutput = new FileOutputStream(file)) {
    mapper.writeValue(fileOutput, studentData);
}

Similarly, we can use ObjectMapper to read our file back into a new HashMap instance:

Map<Integer, Student> mapFromFile;
try (FileInputStream fileInput = new FileInputStream(file)) {
    TypeReference<HashMap<Integer, Student>> mapType 
      = new TypeReference<HashMap<Integer, Student>>() {};
    mapFromFile = mapper.readValue(fileInput, mapType);
}
assertThat(mapFromFile).isEqualTo(studentData);

Because HashMap is a parameterized type, we had to create a TypeReference so Jackson knows how to deserialize our JSON file back into a HashMap<Integer, Student>.

No special interfaces or class modifications were necessary to convert our Student class to JSON – we could even drop the use of the Serializable interface. However, it’s also important to note here that during deserialization, Jackson requires the class to have a default no-argument constructor. Though many classes provide one, this requirement can be an issue if the class can’t be changed.

4.2. Gson

Gson is another common choice for JSON serialization in Java.

We’ll again use our map from above and define a Gson instance to serialize it to a JSON file:

Gson gson = new Gson();
File file = File.createTempFile("student", ".data");
try (FileWriter writer = new FileWriter(file)) {
    gson.toJson(studentData, writer);
}

Reading the file back into a HashMap instance is simple:

Map<Integer, Student> studentsFromFile;
try (FileReader reader = new FileReader(file)) {
    Type mapType = new TypeToken<HashMap<Integer, Student>>() {}.getType();
    studentsFromFile = gson.fromJson(reader, mapType);
}
assertThat(studentsFromFile).isEqualTo(studentData);

Similar to Jackson, Gson needs type information to deserialize the parameterized HashMap – this is provided in the form of a Java Reflection API Type using Gson’s TypeToken.

Gson has the same requirement of a default constructor but provides the InstanceCreator interface to assist in the case where one is not provided.

5. Summary

In this tutorial, we discussed three methods for writing to and reading from a file with HashMap data.

For simple mappings of Strings, Java Properties offers us a straightforward solution. Object serialization is another core Java feature that provides us with more flexibility for classes that we can modify. For cases where we can’t edit the class in question (or if we need a human-readable format), open-source libraries like Jackson and Gson provide useful tools for JSON serialization.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)