Get SubMap From Map In Java

In Java, a submap is a portion or part of the given Map between the keys of a specific range. This article will discuss different techniques to get a submap from a Map.

1. Using Map.keySet().retainAll()

The retainAll() removes all the keys from the Map which are not present in the specified list. Be careful that the retainAll() removes entries from the original collection, so if we do not want to modify the original Map, perform this operation on a new copy of the Map.

Map<String, String> map = new HashMap<>();
map.put("key1", "Value1");
map.put("key2", "Value2");
map.put("key3", "Value3");

List<String> keysToRetain = List.of("key1", "key2");
map.keySet().retainAll(keysToRetain);

System.out.println(map);    //{key1=Value1, key2=Value2}

2. Using TreeMap submap(), headMap() and tailMap()

The TreeMap class stores the key-value pairs sorted by keys in either natural order or using the provider Comparator for custom orders. TreeMap allows getting a submap using the following methods.

  • subMap(fromKey, toKey): returns a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive.
  • headMap(toKey): returns a view of the portion of this map whose keys are strictly less than toKey.
  • tailMap(fromKey): returns a view of the portion of this map whose keys are greater than or equal to fromKey.

We can also use these methods with other Map implementations of the SortedMap and NavigableMap

TreeMap<String, String> treeMap = new TreeMap<>();

treeMap.put("key1", "Value1");
treeMap.put("key2", "Value2");
treeMap.put("key3", "Value3");

SortedMap<String, String> subMap = treeMap.subMap("key2", "key3");      //{key2=Value2}
SortedMap<String, String> headMap = treeMap.headMap("key2");            //{key1=Value1}
SortedMap<String, String> tailMap = treeMap.tailMap("key2");           //{key2=Value2, key3=Value3}

Note that each of the following methods returns a Map backed by the original Map, so changes in the submap are reflected in the original map, and vice-versa.

subMap.put("key2", "NEW_VALUE_2");

System.out.println(subMap);     //{key2=NEW_VALUE_2}
System.out.println(treeMap);    //{key1=Value1, key2=NEW_VALUE_2, key3=Value3}

Similarly, adding new entries to the original Map will also change the Map views. For example, adding a new key-value pair key4:value4 in the original map is reflected in all submap views.

treeMap.put("key4", "value4");

System.out.println(tailMap);     //{key2=NEW_VALUE_2, key3=Value3, key4=value4}
System.out.println(treeMap);    //{key1=Value1, key2=NEW_VALUE_2, key3=Value3, key4=value4}

See Also: HashMap vs TreeMap

3. Using Stream API

A Stream is a collection or sequence of data from the source. We can use the Stream API to traverse, filter and collect the desired key-value pairs into a new Map.

The new Map is not backed by the original Map so we can change the entries in both Maps without altering the other Map.

Map<Integer, String> hashmap = new HashMap<>();
hashmap.put(1, "Value1");
hashmap.put(2, "Value2");
hashmap.put(3, "Value3");

List<Integer> keysList = Arrays.asList(1, 2);

Map<Integer, String> subHashmap = hashmap.entrySet()
        .stream()
        .filter(x -> keysList.contains(x.getKey()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

System.out.println(subHashmap);     //{1=Value1, 2=Value2}

4. Using Guava’s Maps Class

Guava is a set of standard libraries that provides various utility methods. Its Maps class provides the following utility methods for getting a new Map by filtering keys or values from the specified Map.

  • Maps.filterKeys(unfilteredMap, keyPredicate)
  • Maps.filterValues(unfilteredMap, valuePredicate)
  • Maps.filterEntries(unfilteredMap, entryPredicate)

In each method, we pass the originalMap and a Predicate that matches either key, value or entry to be populated in the submap.

Map<Integer, String> hashmap = new HashMap<>();
hashmap.put(1, "Value1");
hashmap.put(2, "Value2");
hashmap.put(3, "Value3");

List<Integer> keysList = Arrays.asList(1, 2);

Map<Integer, String> subMap = Maps.filterKeys(hashmap, Predicates.in(keysList));

System.out.print(subMap);  //{1=Value1, 2=Value2}

5. Conclusion

In This Java tutorial, we learned to get a submap from a specified Map using different techniques from Map APIs and Stream API to Guava filter() methods. To get a submap independent of original Map, we have to iterate over the Map entries and create a new Map from selected entries.

Happy Learning!!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode