Previously, we saw the collection framework hierarchy and how Collection
is the root of it. There exists another interface that didn’t quite fit into that hierarchy but is an extremely important part of the collection framework, the Map
.
Map
defines a generic interface for an object that holds key-value pairs as elements. The key is used to retrieve (like the index in an array or List
) some value. A key must be unique and map to exactly one value. A Map
can be thought of as a Java interface for a Hash Table data structure. We are given many implementations of a Map
but we’ll focus on the HashMap
, LinkedHashMap
, and TreeMap
implementations.
The HashMap
defines no specific ordering for the keys and is the most optimized implementation for retrieving values.
The LinkedHashMap
keeps the keys in insertion order and is slightly less optimal than the HashMap
.
The TreeMap
keeps keys in their natural order (or some custom order defined using a Comparator
). This implementation has a significant performance decrease compared to HashMap
and LinkedHashMap
but is great when needing to keep keys sorted.
A Map
has the following methods for accessing its elements:
put()
: Sets the value that key maps to. Note that this method replaces the value key mapped to if the key was already present in the Map
.
get()
: Gets, but does not remove, the value the provided key argument points to if it exists. This method returns null
if the key is not in the Map
.
Let’s see how we can use them:
Map<String, String> myMap = new HashMap<>(); myMap.put("Hello", "World") // { "Hello" -> "World" } myMap.put("Name", "John") // { "Hello" -> "World" }, { "Name" -> "John" } String result = myMap.get("Hello") // returns "World" String noResult = myMap.get("Jack") // return `null`
In the example above we:
- Created a
Map
reference that maps aString
key to aString
value using theHashMap
implementation. Note that aMap
needs a type argument for the key and value. - Added key-value pairs to
myMap
usingput()
where the first argument is the key and the second is the value the key maps to. - Retrieved the value the key “Hello” maps to using
get()
. TheString
“World” is returned since the key “Hello” exists.get()
returnsnull
because the key “Jack” does not exist.
We can iterate over a Map
with an enhanced for-loop
like:
// Given a map, `myMap`, with the following key-value pairs { "Hello" -> "World" }, { "Name" -> "John"} for (Map.Entry<String, String> pair: myMap.entrySet()){ System.out.println("key: "+pair.getKey()+", value: "+pair.getValue()); } // OUTPUT TERMINAL: // key: Name, value: John // key: Hello, value: World
In the example above we:
- Called
entrySet()
that returns aSet
of typeMap.Entry
which represents a key-value pair. - We define our iterating variable of type
Map.Entry<String, String>
to specify what type of key-value pair we are iterating over. - Called
getKey()
ofMap.Entry
to get the key of the pair. - Called
getValue()
ofMap.Entry
to get the value of the pair.
Let’s practice working with Map
.
Instructions
In Main.java we’ve defined a method named countNumbers()
that should take an Integer List
named list
as a parameter and returns a Map
of the Integer
as a key and the number of times it appears in the list
as its value.
Let’s complete the body of countNumbers
by first defining a Map
reference where the keys and values will be Integer
s and name it intCount
. Use a Map
implementation that will keep keys stored in sorted order.
Note: It’s okay to see an error in the console about a missing return statement.
Let’s iterate through list
and keep count of the Integer
s we come across.
In countNumbers()
define an enhanced for-loop
that iterates over list
using an Integer
named i
. Complete the following tasks:
- In the body of the
for-loop
define anInteger
reference namedcurrentCount
and set it to the value returned from gettingi
fromintCount
. - Create and
if
block that checks ifcurrentCount
is notnull
. - In the body of the
if
block create anint
type namednewCount
and set it equal tocurrentCount
incremented by1
. - In the body of the
if
block update the keyi
inintCount
withnewCount
. - Create an
else
block that will add the keyi
tointCount
with an initial value of1
.
Note: It’s okay to see an error in the console about a missing return statement.
Let’s return are completed count of Integer
s.
In countNumbers()
return intCount
and run the program. You should see the integers and the number of times they’ve appeared in myInts
.