Diamond operator in Java
new ArrayList<>() infers type arguments.
Map<String, List<Integer>> scores = new HashMap<String, List<Integer>>(); Saying everything twice is tiring. Java 7 gave us two characters that fix it, plus one trap with var.Say it once
Since Java 7, the **diamond <> tells the compiler: infer the type arguments from the context**, usually the variable's declared type.
Map<String, List<Integer>> scores =
new HashMap<>(); // <String, List<Integer>>
List<String> names = new ArrayList<>();<> vs nothing at all
List<String> l = new ArrayList();No <> at all creates a raw ArrayList: unchecked warnings, and the compiler stops checking element types.
List<String> l = new ArrayList<>();The diamond infers <String>: fully type-checked, no repetition.
var + diamond = Object
The diamond infers from the left-hand side. With var, there is no left-hand type, so the compiler falls back to **ArrayList<Object>**.
var list = new ArrayList<>();
// list is ArrayList<Object>Your turn
What does this print?
var list = new ArrayList<>();
list.add(3);
list.add("three");
System.out.println(list);Compile error[3, three]Throws ClassCastException
Show the answer
list is an ArrayList<Object>. An Integer and a String are both Objects, so both adds compile and it prints [3, three].
Use what you stored
Now try to use the String. What happens?
var list = new ArrayList<>();
list.add("hey");
System.out.println(list.get(0).toUpperCase());Prints HEYCompile errorThrows ClassCastException
Show the answer
For an ArrayList<Object>, get(0) returns **Object**, and Object has no toUpperCase(). Compile error, even though the element really is a String.
Pick one side for the type
Write the type once, on one side: either on the left with a diamond on the right, or with var on the left and the full type on the right. Since Java 9, the diamond also works with anonymous classes.
List<String> a = new ArrayList<>(); // ✓
var b = new ArrayList<String>(); // ✓
var c = new ArrayList<>(); // Object!In code review
new HashMap<>() is everywhere in modern Java. Reviewers flag two smells: a missing <> (an accidental raw type, which triggers "unchecked" warnings) and var x = new ArrayList<>(), which quietly makes a list of Object.
Key takeaways
- List<String> l = new ArrayList<>(); // infers <String>
- new ArrayList() without <> is a raw type — not the same thing
- var l = new ArrayList<>(); // ArrayList<Object>
- Since Java 9 the diamond also works with anonymous classes
The <> was nicknamed "diamond" for its shape. It arrived in Java 7 as part of Project Coin, a bundle of small language improvements that also brought try-with-resources and strings in switch.
Practice questions
Pick the shortest correct way to complete the line.
Map<String, List<Integer>> scores =
new HashMap___();- <>
- <?, ?>
- <String>
- []
Check your answer
<>. The diamond infers <String, List<Integer>>. <String> has the wrong number of arguments, and you can't instantiate a wildcard type like HashMap<?, ?>.
What is the difference between new ArrayList<>() and new ArrayList()?
- None — both infer the type
- The first infers type arguments; the second creates a raw type and loses generic type checks
- The second is faster because it skips generics
- The first only works for Strings
Check your answer
The first infers type arguments; the second creates a raw type and loses generic type checks. Leaving out <> entirely makes a raw ArrayList, which produces unchecked warnings and lets wrong types slip in.