DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How does AI transform chaos engineering from an experiment into a critical capability? Learn how to effectively operationalize the chaos.

Data quality isn't just a technical issue: It impacts an organization's compliance, operational efficiency, and customer satisfaction.

Are you a front-end or full-stack developer frustrated by front-end distractions? Learn to move forward with tooling and clear boundaries.

Developer Experience: Demand to support engineering teams has risen, and there is a shift from traditional DevOps to workflow improvements.

Related

  • Jakarta WebSocket Essentials: A Guide to Full-Duplex Communication in Java
  • Java Is Greener on Arm
  • Mastering Date/Time APIs: Challenges With Java's Calendar and JDK Date/Time APIs
  • Java 23: What Developers Need to Know

Trending

  • Automating Sentiment Analysis Using Snowflake Cortex
  • What Is Plagiarism? How to Avoid It and Cite Sources
  • RAG vs. CAG: A Deep Dive into Context-Aware AI Generation Techniques
  • Engineering Resilience Through Data: A Comprehensive Approach to Change Failure Rate Monitoring
  1. DZone
  2. Coding
  3. Java
  4. Handy New Map Default Methods in JDK 8

Handy New Map Default Methods in JDK 8

By 
Dustin Marx user avatar
Dustin Marx
·
Apr. 21, 14 · Interview
Likes (1)
Comment
Save
Tweet
Share
18.4K Views

Join the DZone community and get the full member experience.

Join For Free

The Map interface provides some handy new methods in JDK 8. Because the Map methods I cover in this post are implemented as default methods, all existing implementations of the Map interface enjoy the default behaviors defined in the default methods without any new code. The JDK 8 introduced Map methods covered in this post are getOrDefault(Object, V), putIfAbsent(K, V), remove(Object, Object), remove(Object, Object), replace(K, V), and replace(K, V, V).

Example Map for Demonstrations

I will be using the Map declared and initialized as shown in the following code throughout the examples in this blog post. The statesAndCapitals field is a class-level static field. I intentionally have only included a small subset of the fifty states in the United States for reading clarity and to allow easier demonstration of some of the new JDK 8 Map default methods.

   private final static Map<string, string=""> statesAndCapitals;

   static
   {
      statesAndCapitals = new HashMap<>();
      statesAndCapitals.put("Alaska", "Anchorage");
      statesAndCapitals.put("California", "Sacramento");
      statesAndCapitals.put("Colorado", "Denver");
      statesAndCapitals.put("Florida", "Tallahassee");
      statesAndCapitals.put("Nevada", "Las Vegas");
      statesAndCapitals.put("New Mexico", "Sante Fe");
      statesAndCapitals.put("Utah", "Salt Lake City");
      statesAndCapitals.put("Wyoming", "Cheyenne");
   }

Map.getOrDefault(Object, V)

Map's new method getOrDefault(Object, V) allows the caller to specify in a single statement to get the value of the map that corresponds to the provided key or else return a provided "default value" if no match is found for the provided key.

The next code listing compares how checking for a value matching a provided key in a map or else using a default if no match is found was implemented before JDK 8 and how it can now be implemented with JDK 8.

/*
 * Demonstrate Map.getOrDefault and compare to pre-JDK 8 approach. The JDK 8
 * addition of Map.getOrDefault requires fewer lines of code than the
 * traditional approach and allows the returned value to be assigned to a
 * "final" variable.
 */

// pre-JDK 8 approach
String capitalGeorgia = statesAndCapitals.get("Georgia");
if (capitalGeorgia == null)
{
   capitalGeorgia = "Unknown";
}

// JDK 8 approach
final String capitalWisconsin = statesAndCapitals.getOrDefault("Wisconsin", "Unknown");

The Apache Commons class DefaultedMap provides functionality similar to the newMap.getOrDefault(Object, V) method. The Groovy GDK includes a similar method for Groovy,Map.get(Object, Object), but that one's behavior is a bit different because it not only returns the provided default if the "key" is not found, but also adds the key with the default value to the underlying map.

Map.putIfAbsent(K, V)

Map's new method putIfAbsent(K, V) has Javadoc advertising its default implementation equivalent:

The default implementation is equivalent to, for this map:
 
 V v = map.get(key);
 if (v == null)
     v = map.put(key, value);

 return v;

This is illustrated with another code sample that compares the pre-JDK 8 approach to the JDK 8 approach.

/*
 * Demonstrate Map.putIfAbsent and compare to pre-JDK 8 approach. The JDK 8
 * addition of Map.putIfAbsent requires fewer lines of code than the
 * traditional approach and allows the returned value to be assigned to a
 * "final" variable.
 */

// pre-JDK 8 approach
String capitalMississippi = statesAndCapitals.get("Mississippi");
if (capitalMississippi == null)
{
   capitalMississippi = statesAndCapitals.put("Mississippi", "Jackson");
}

// JDK 8 approach
final String capitalNewYork = statesAndCapitals.putIfAbsent("New York", "Albany");

Alternate solutions in the Java space before the addition of this putIfAbsent method are discussed in theStackOverflow thread Java map.get(key) - automatically do put(key) and return if key doesn't exist?. It's worth noting that before JDK 8, the ConcurrentMap interface (extends Map) already provided a putIfAbsent(K, V)method.

Map.remove(Object, Object)

Map's new remove(Object, Object) method goes beyond the long-available Map.remove(Object) method to remove a map entry only if both the provided key and provided value match an entry in the map (the previously available version only looked for a "key" match to remove).

The Javadoc comment for this method explains the how the default method's implementation works in terms of equivalent pre-JDK 8 Java code:

The default implementation is equivalent to, for this map:

if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
     map.remove(key);
     return true;
 } else
     return false;

A concrete comparison of the new approach to the pre-JDK 8 approach is shown in the next code listing.

/*
 * Demonstrate Map.remove(Object, Object) and compare to pre-JDK 8 approach.
 * The JDK 8 addition of Map.remove(Object, Object) requires fewer lines of
 * code than the traditional approach and allows the returned value to be
 * assigned to a "final" variable.
 */

// pre-JDK 8 approach
boolean removed = false;
if (   statesAndCapitals.containsKey("New Mexico")
    && Objects.equals(statesAndCapitals.get("New Mexico"), "Sante Fe"))
{
   statesAndCapitals.remove("New Mexico", "Sante Fe");
   removed = true;
}

// JDK 8 approach
final boolean removedJdk8 = statesAndCapitals.remove("California", "Sacramento");

Map.replace(K, V)

The first of the two new Map "replace" methods sets the specified value to be mapped to the specified key only if the specified key already exists with some mapped value. The Javadoc comment explains the Java equivalent of this default method implementation:

The default implementation is equivalent to, for this map:

 if (map.containsKey(key)) {
     return map.put(key, value);
 } else
     return null;

The comparison of this new approach to the pre-JDK 8 approach is shown next.

/*
 * Demonstrate Map.replace(K, V) and compare to pre-JDK 8 approach. The JDK 8
 * addition of replace(K, V) requires fewer lines of code than the traditional
 * approach and allows the returned value to be assigned to a "final" 
 * variable.
 */

// pre-JDK 8 approach
String replacedCapitalCity;
if (statesAndCapitals.containsKey("Alaska"))
{
   replacedCapitalCity = statesAndCapitals.put("Alaska", "Juneau");
}

// JDK 8 approach
final String replacedJdk8City = statesAndCapitals.replace("Alaska", "Juneau");

Map.replace(K, V, V)

The second newly added Map "replace" method is more narrow in its interpretation of which existing values are replaced. While the method just covered replaces any value in a value available for the specified key in the mapping, this "replace" method that accepts an additional (third) argument will only replace the value of a mapped entry that has both a matching key and a matching value. The Javadoc comment shows the default method's implementation:

The default implementation is equivalent to, for this map:
 
 if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
     map.put(key, newValue);
     return true;
 } else
     return false;

My comparison of this approach to the pre-JDK 8 approach is shown in the next code listing.

/*
 * Demonstrate Map.replace(K, V, V) and compare to pre-JDK 8 approach. The
 * JDK 8 addition of replace(K, V, V) requires fewer lines of code than the
 * traditional approach and allows the returned value to be assigned to a
 * "final" variable.
 */

// pre-JDK 8 approach
boolean replaced = false;
if (   statesAndCapitals.containsKey("Nevada")
    && Objects.equals(statesAndCapitals.get("Nevada"), "Las Vegas"))
{
   statesAndCapitals.put("Nevada", "Carson City");
   replaced = true;
}

// JDK 8 approach
final boolean replacedJdk8 = statesAndCapitals.replace("Nevada", "Las Vegas", "Carson City");
Observations and Conclusion

There are several observations to make from this post.

  • The Javadoc methods for these new JDK 8 Map methods are very useful, especially in terms of describing how the new methods behave in terms of pre-JDK 8 code. I discussed these methods' Javadoc in a more general discussion on JDK 8 Javadoc-based API documentation.
  • As the equivalent Java code in these methods' Javadoc comments indicates, these new methods do not generally check for null before accessing map keys and values. Therefore, one can expect the same issues with nulls using these methods as one would find when using "equivalent" code as shown in the Javadoc comments. In fact, the Javadoc comments generally warn about the potential forNullPointerException and issues related to some Map implementations allowing null and some not for keys and values.
  • The new Map methods discussed in this post are "default methods," meaning that implementations of Map "inherit" these implementations automatically.
  • The new Map methods discussed in this post allow for cleaner and more concise code. In most of my examples, they allowed the client code to be converted from multiple state-impacting statements to a single statement that can set a local variable once and for all.

The new Map methods covered in this post are not ground-breaking or earth-shattering, but they are conveniences that many Java developers previously implemented more verbose code for, wrote their own similar methods for, or used a third-party library for. JDK 8 brings these standardized methods to the Java masses without need for custom implementation or third-party frameworks. Because default methods are the implementation mechanism, even Map implementations that have been around for quite a while suddenly and automatically have access to these new methods without any code changes to the implementations.


Java (programming language) Java Development Kit

Published at DZone with permission of Dustin Marx, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Jakarta WebSocket Essentials: A Guide to Full-Duplex Communication in Java
  • Java Is Greener on Arm
  • Mastering Date/Time APIs: Challenges With Java's Calendar and JDK Date/Time APIs
  • Java 23: What Developers Need to Know

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: