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

In this tutorial, we’ll learn how to use the IdentityHashMap class in Java. We’ll also examine how it differs from the general HashMap class. Though this class implements the Map interface, it violates the contract of the Map interface.

For more detailed documentation, we can refer to the IdenityHashMap java doc page. For more details on the general HashMap class, we can read A Guide to Java HashMap.

2. About the IdentityHashMap Class

This class implements the Map interface. The Map interface mandates the use of the equals() method on the key comparison. However, the IdentityHashMap class violates that contract. Instead, it uses reference equality (==) on key search operations.

During search operations, HashMap uses the hashCode() method for hashing, whereas IdentityHashMap uses the System.identityHashCode() method. It also uses the linear probe technique of the hashtable for search operations.

The use of reference equality, System.identityHashCode(), and the linear probe technique give the IdentityHashMap class a better performance.

3. Using the IdentityHashMap Class

Object construction and method signatures are the same as HashMap, but the behavior is different due to reference equality.

3.1. Creating IdentityHashMap Objects

We can create it using the default constructor:

IdentityHashMap<String, String> identityHashMap = new IdentityHashMap<>();

Or it can be created using the initial expected capacity:

IdentityHashMap<Book, String> identityHashMap = new IdentityHashMap<>(10);

If we don’t specify the initial expectedCapcity parameter as we did above, it uses 21 as the default capacity.

We can also create it using another map object:

IdentityHashMap<String, String> identityHashMap = new IdentityHashMap<>(otherMap);

In this case, it initializes the created identityHashMap with the entries of otherMap.

3.2. Add, Retrieve, Update and Remove Entries

The put() method is used to add an entry:

identityHashMap.put("title", "Harry Potter and the Goblet of Fire");
identityHashMap.put("author", "J. K. Rowling");
identityHashMap.put("language", "English");
identityHashMap.put("genre", "Fantasy");

We can also add all of the entries from the other map using the putAll() method:

identityHashMap.putAll(otherMap);

To retrieve values, we use the get() method:

String value = identityHashMap.get(key);

To update a value for a key, we use the put() method:

String oldTitle = identityHashMap.put("title", "Harry Potter and the Deathly Hallows");
assertEquals("Harry Potter and the Goblet of Fire", oldTitle);

In the above snippet, the put() method returns the old value after the update. The second statement ensures that oldTitle matches the earlier “title” value.

We can use the remove() method to remove an element:

identityHashMap.remove("title");

3.3. Iterate Through All Entries

We can iterate through all the entries using the entitySet() method:

Set<Map.Entry<String, String>> entries = identityHashMap.entrySet();
for (Map.Entry<String, String> entry: entries) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

We can also iterate through all the entries using the keySet() method:

for (String key: identityHashMap.keySet()) {
    System.out.println(key + ": " + identityHashMap.get(key));
}

These iterators use a fail-fast mechanism. If the map is modified while iterating, it throws a ConcurrentModificationException.

3.4. Other Methods

We also have different methods available that work similarly to other Map objects:

  • clear(): removes all entries
  • containsKey(): finds whether a key exists in the map or not. Only references are equated
  • containsValue(): finds whether the value exists in the map. Only references are equated
  • keySet(): returns an identity-based keyset
  • size(): returns the number of entries
  • values(): returns a collection of values

3.5. Support for Null Keys and Null Values

IdentityHashMap allows null for both the key and value:

IdentityHashMap<String, String> identityHashMap = new IdentityHashMap<>();
identityHashMap.put(null, "Null Key Accepted");
identityHashMap.put("Null Value Accepted", null);
assertEquals("Null Key Accepted", identityHashMap.get(null));
assertEquals(null, identityHashMap.get("Null Value Accepted"));

The above snippet ensures null both as key and value.

3.6. Concurrency With IdentityHashMap

IdentityHashMap isn’t threadsafe, the same as HashMap. So if we have multiple threads to access/modify IdentityHashMap entries in parallel, we should convert them to the synchronized map.

We can get a synchronized map using the Collections class:

Map<String, String> synchronizedMap = Collections.synchronizedMap(new IdentityHashMap<String, String>());

4. Example Usage of Reference Equality

IdentityHashMap uses reference equality (==) over the equals() method to search/store/access key objects.

An IdentityHashMap created with four properties:

IdentityHashMap<String, String> identityHashMap = new IdentityHashMap<>();
identityHashMap.put("title", "Harry Potter and the Goblet of Fire");
identityHashMap.put("author", "J. K. Rowling");
identityHashMap.put("language", "English");
identityHashMap.put("genre", "Fantasy");

Another HashMap created with the same properties:

HashMap<String, String> hashMap = new HashMap<>(identityHashMap);
hashMap.put(new String("genre"), "Drama");
assertEquals(4, hashMap.size());

When using a new string object genre” as a key, HashMap equates it with the existing key and updates the value. Hence, the size of the hash map remains the same as 4.

The following code snippet shows how IdentityHashMap behaves different:

identityHashMap.put(new String("genre"), "Drama");
assertEquals(5, identityHashMap.size());

IdentityHashMap considers the new “genre” string object as a new key. Hence, it asserts size to be 5. Two different objects of “genre” are used as two keys, with Drama and Fantasy as values.

5. Mutable Keys

IdentityHashMap allows mutable keys. This is yet another useful feature of this class.

Here we’ll take a simple Book class as a mutable object:

class Book {
    String title;
    int year;
    
    // other methods including equals, hashCode and toString
}

First, two mutable objects of Book class are created:

Book book1 = new Book("A Passage to India", 1924);
Book book2 = new Book("Invisible Man", 1953);

Following code shows mutable key usage with HashMap:

HashMap<Book, String> hashMap = new HashMap<>(10);
hashMap.put(book1, "A great work of fiction");
hashMap.put(book2, "won the US National Book Award");
book2.year = 1952;
assertEquals(null, hashMap.get(book2));

Though the book2 entry is present in HashMap, it couldn’t retrieve its value. Because it has been modified and equals() method now doesn’t equate with the modified object. This is why general Map objects mandate immutable objects as a key.

The below snippet uses the same mutable keys with IdentityHashMap:

IdentityHashMap<Book, String> identityHashMap = new IdentityHashMap<>(10);
identityHashMap.put(book1, "A great work of fiction");
identityHashMap.put(book2, "won the US National Book Award");
book2.year = 1951;
assertEquals("won the US National Book Award", identityHashMap.get(book2));

Interestingly, IdentityHashMap is able to retrieve values even when the key object has been modified. In the above code, assertEquals ensures that the same text is retrieved again. This is possible due to reference equality.

6. Comparing Values

Up to Java 20, the IdentityHashMap had non-obvious behavior regarding values. While all the keys were compared by their identity, the values were still compared by their equality. This happened while using two methods: remove(Object, Object) and replace(Object, Object, Object).

Let’s check the first method. It removes an entry if both key and value match:

Book book = new Book("A Passage to India", 1924);
IdentityHashMap<Book, String> identityHashMap = new IdentityHashMap<>(10);
identityHashMap.put(book, "A great work of fiction");
identityHashMap.remove(book, new String("A great work of fiction"));
assertEquals(null, identityHashMap.get(book));

The second method is similar to the first one, but it replaces the value of the entry, where the key and the value match:

Book book = new Book("A Passage to India", 1924);
IdentityHashMap<Book, String> identityHashMap = new IdentityHashMap<>(10);
identityHashMap.put(book, "A great work of fiction");
identityHashMap.replace(book, new String("A great work of fiction"), "One of the greatest books");
assertEquals("One of the greatest books", identityHashMap.get(book));

The main issue is that the IdentityHashMap, until Java 20, didn’t override these methods and used default implementations from Map. Thus, it’s important to know about this issue, as upgrading to Java 20 and above might introduce undesired behavior and hard-to-debug bugs. 

Overall the fix would produce the following result for the first example:

Book book = new Book("A Passage to India", 1924);
IdentityHashMap<Book, String> identityHashMap = new IdentityHashMap<>(10);
identityHashMap.put(book, "A great work of fiction");
identityHashMap.remove(book, new String("A great work of fiction"));
assertEquals("A great work of fiction", identityHashMap.get(book));

The following result would be produced for the second method:

Book book = new Book("A Passage to India", 1924);
IdentityHashMap<Book, String> identityHashMap = new IdentityHashMap<>(10);
identityHashMap.put(book, "A great work of fiction");
identityHashMap.replace(book, new String("A great work of fiction"), "One of the greatest books");
assertEquals("A great work of fiction", identityHashMap.get(book));

7. Some Use Cases

As a result of its features, IdentiyHashMap stands apart from other Map objects. However, it isn’t used for general purposes, and therefore we need to be cautious while using this class.

It’s helpful in building specific frameworks, including:

  • Maintaining proxy objects for a set of mutable objects
  • Building a quick cache based on an object reference
  • Keeping an in-memory graph of objects with references

8. Conclusion

In this article, we learned how to work with IdentityHashMap, how it differs from general HashMap, and some use cases.

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)