Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

The Diamond Operator Simplifies Life

Posted on May 22, 2012 By Luis Fernandez

I finally stopped squinting at angle brackets today, and it feels like my code exhaled.

The Java diamond operator has been sitting in my editor for a while, but today it clicked for real. You know that little pair of empty brackets in new HashMap<>(). That is the one. It strips noise from generics by letting the compiler infer the types on the right hand side. No more repeating the whole type saga. My brain thanks me, my diff view thanks me, and code reviews move faster. In a week filled with talk about try with resources and multi catch, this tiny feature is the one making my daily grind smoother.

Before and after in plain sight

First let us look at the kind of thing I still see in old repos and in many blog posts. The classic verbose version that made us scroll more than we wanted:

// Before: repeat yourself and then repeat yourself again
Map<String, List<Integer>> scores = new HashMap<String, List<Integer>>();

List<Map.Entry<Long, String>> entries = new ArrayList<Map.Entry<Long, String>>();

Comparator<List<String>> comp = new Comparator<List<String>>() {
    @Override public int compare(List<String> a, List<String> b) {
        return a.size() - b.size();
    }
};

Now the same code with the diamond. The first time you try it, you almost expect a red squiggle. Then the build passes and you smile:

// After: let the compiler read what you wrote on the left
Map<String, List<Integer>> scores = new HashMap<>();

List<Map.Entry<Long, String>> entries = new ArrayList<>();

Comparator<List<String>> comp = new Comparator<>() {
    @Override public int compare(List<String> a, List<String> b) {
        return a.size() - b.size();
    }
};

Same types. Less ceremony. The intent stands out. In code review I want to read what we are doing, not fight a wall of angle brackets. The diamond operator gives you that breathing room while keeping everything type safe. It is not just syntactic sugar. It makes the signal louder.

Fewer mistakes, cleaner diffs

Repeating a long generic line invites small typos. One missed letter in a nested type and you get a cryptic compiler message. With the diamond, the source of truth is the left side. Your diffs also get smaller, which is gold for any team doing pull requests or code reviews over email. We spend real time scanning changes. Shorter diffs cut that time. The win shows up every day.

There is a subtle perk in IDE hints too. In IDEA and the newer Eclipse builds, type inference plays nicely with completion. The right side stays lean, the left side gives the hint you want. If you have ever used Guava and filled a line with nested generics, the diamond turns that into something you can read in one sip.

// Guava style before
LoadingCache<String, List<UUID>> cache = CacheBuilder.newBuilder()
    .maximumSize(1000)
    .build(new CacheLoader<String, List<UUID>>() {
        @Override public List<UUID> load(String key) {
            return new ArrayList<UUID>();
        }
    });

// With diamond
LoadingCache<String, List<UUID>> cache = CacheBuilder.newBuilder()
    .maximumSize(1000)
    .build(new CacheLoader<>() {
        @Override public List<UUID> load(String key) {
            return new ArrayList<>();
        }
    });

Where it shines and where it bites

It shines in collection construction, in anonymous classes, and in any spot where the left side already spells out a clear type. It also reads nicely when you pass a new object straight into a method:

process(new HashMap<>());
renderUsers(new ArrayList<>(users));
Optional<String> name = Optional.fromNullable(fetchName()); // Guava Optional

There are a few bites. If the compiler cannot infer the type from context, you will get a grumpy message. For example, method references are not here yet and raw types still exist in old code. If you pass a diamond constructed value where the expected type is not obvious, you may need to keep the explicit type or add a helper variable so the context is clear. That is rare, and it is usually a design smell anyway.

Builds, tools, and one big asterisk

To use the diamond, your toolchain needs to target the newer compiler level. In Maven that is the maven compiler plugin with source and target set the same. In Gradle the source and target settings do the trick. Editors already catch up fast. If your project still ships with older settings, this is a great time to bump them and clean the codebase. The code gets clearer and you do not change behavior.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>2.5.1</version>
  <configuration>
    <source>1.7</source>
    <target>1.7</target>
  </configuration>
</plugin>

Android note: the standard Android toolchain still compiles with an older level. That means no diamond in your app code yet. Library code that targets the regular JVM can enjoy it. For shared modules, keep an eye on the lowest common setup or split modules so both paths are happy.

Why this small thing matters for teams

We talk a lot about big rewrites, new frameworks, and shiny libraries. Most days are not that. Most days we read code, we patch code, and we try to keep bugs from sneaking in. Features that remove clutter from what we read are the ones that pay the rent. The diamond operator earns a spot on that list. It pushes intent forward and shoves ceremony to the side. That is the sort of change that sticks.

// A tiny refactor that reads better right away
Map<UserId, Set<Role>> rolesByUser = new HashMap<>();
rolesByUser.put(user.getId(), new HashSet<>(defaultRoles));

Clean code is inviting. The next developer will walk in and see what you meant. When types fade into the background and names carry the story, we move faster as a group. If your team is on the fence, open one pull request that swaps obvious spots to the diamond. Let the diff speak. My bet is that nobody will miss the extra brackets.


Less noise, more signal.

Hello diamond operator.

Code Development Practices Software Engineering coding-practicesjavaspring

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes