It's just a process of continual improvement.
Originally, Java didn't have generics, and so you had to use the first form in your question. The ArrayList
carried no information about what kind of objects it contained; they were just Object
. A lot of casting was involved, e.g.:
ArrayList list = new ArrayList();
list.add(new Thing());
// ...
Thing t = (Thing)list.get(0);
// Blech--^^^^^^^
So Java got generics, and we could say what the ArrayList
would contain1:
ArrayList<Thing> list = new ArrayList<Thing>();
list.add(new Thing());
// ...
Thing t = list.get(0);
// ^--- No cast! :-)
But note the redundancy, I've had to write ArrayList<Thing>
twice. (Well, really, I should have List<Thing> list = new ArrayList<Thing>();
, but that's another issue.)
And so Java got the ability to infer the type parameter (<Thing>
) from the variable declaration, which is where <>
comes from:
ArrayList<Thing> list = new ArrayList<>();
// No need to repeat ----------------^^
list.add(new Thing());
// ...
Thing t = list.get(0);
// ^--- No cast! :-)
In that example, it doesn't save a lot of typing, but consider a more complicated case, say a map mapping strings to lists of Thing
:
Map<String, List<Thing>> map = new HashMap<>();
...is rather shorter / less redundant than
Map<String, List<Thing>> map = new HashMap<String, List<Thing>>();
1 The actual list still just works in terms of Object
, it's just that the variable carries the type parameter information with it at compile-time (and a little bit at runtime) and the compiler inserts the casts for us; more in this answer. This was in order to provide backward-compatibility when generics were added to Java.