Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we'll discuss how to get the first key-value pair from a HashMap without knowing the key.

First, we'll use an iterator, and then a stream to get the first entry. Finally, we'll discuss a problem the HashMap presents when we want to get the first entry and how to solve it.

2. Using an Iterator

Let's consider we have the following HashMap<Integer, String>:

Map<Integer, String> hashMap = new HashMap<>();
hashMap.put(5, "A");
hashMap.put(1, "B");
hashMap.put(2, "C");

In this example, we'll use an iterator to get the first key-value pair. So, let's create an iterator on the entry set of the HashMap and call the next() method to retrieve the first entry:

Iterator<Map.Entry<Integer, String>> iterator = hashMap.entrySet().iterator();

Map.Entry<Integer, String> actualValue = iterator.next();
Map.Entry<Integer, String> expectedValue = new AbstractMap.SimpleEntry<Integer, String>(1, "B");

assertEquals(expectedValue, actualValue);

3. Using a Java Stream

Another approach is to use the Java Stream API. Let's create a stream on the entry set and call the findFirst() method to get its first entry:

Map.Entry<Integer, String> actualValue = hashMap.entrySet()
  .stream()
  .findFirst()
  .get();
Map.Entry<Integer, String> expectedValue = new AbstractMap.SimpleEntry<Integer, String>(1, "B");

assertEquals(expectedValue, actualValue);

4. Problem With the Insertion Order

To present this problem, let's remember how we created hashMap, the pair 5=A was inserted as the first entry, then  1=B and finally 2=C. Let's check this by printing the content of our HashMap:

System.out.println(hashMap);
{1=B, 2=C, 5=A}

As we can see, ordering is not the same. The HashMap class implementation doesn't guarantee the insertion order.

Let's now add one more element to hashMap:

hashMap.put(0, "D");

Iterator<Map.Entry<Integer, String>> iterator = hashMap.entrySet().iterator();

Map.Entry<Integer, String> actualValue = iterator.next();
Map.Entry<Integer, String> expectedValue = new AbstractMap.SimpleEntry<Integer, String>(0, "D");

assertEquals(expectedValue, actualValue);

As we can see, the first entry has changed again (to 0=D in this case). This also proves that HashMap doesn't guarantee an insertion order.

So, if we want to preserve the order, we should use a LinkedHashMap instead:

Map<Integer, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put(5, "A");
linkedHashMap.put(1, "B");
linkedHashMap.put(2, "C");
linkedHashMap.put(0, "D");

Iterator<Map.Entry<Integer, String>> iterator = linkedHashMap.entrySet().iterator();
Map.Entry<Integer, String> actualValue = iterator.next();
Map.Entry<Integer, String> expectedValue = new AbstractMap.SimpleEntry<Integer, String>(5, "A");

assertEquals(expectedValue, actualValue);

5. Conclusion

In this short article, we discussed different approaches to get the first entry from a HashMap.

The most important point to note is that HashMap implementation doesn't guarantee any order of insertion. So, if we're interested in preserving the insertion order, we should use a LinkedHashMap.

The code example is available over on GitHub.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
Comments are closed on this article!