Filter map by value

Following the same principles found in filtering a map by keys and filtering a map by entries, this example will show how to filter a map by values while using java, java 8 and guava. The snippets below will use a map defined in the @setup that contains entries of months where the key is the integer month (2=February) of year and the value represents the month spelled out.

Setup

Map<Integer, String> MONTHS = new HashMap<Integer, String>();

@Before
public void setUp () {

    MONTHS.put(new Integer(1), "January");
    MONTHS.put(new Integer(2), "February");
    MONTHS.put(new Integer(3), "March");
    MONTHS.put(new Integer(4), "April");
    MONTHS.put(new Integer(5), "May");
    MONTHS.put(new Integer(6), "June");
    MONTHS.put(new Integer(7), "July");
    MONTHS.put(new Integer(8), "August");
    MONTHS.put(new Integer(9), "September");
    MONTHS.put(new Integer(10), "October");
    MONTHS.put(new Integer(11), "November");
    MONTHS.put(new Integer(12), "December");
}

Straight up Java

Until java 8, the core jdk lack the mechanics for filtering a map by Map.value. The snippet below shows the only effective way is to iterate over the Map.entrySet using a enhanced for loop and then applying criteria in an if statement, in this case checking if entry.value ends with "r".

@Test
public void filter_map_by_values_java () {
    
    Map<Integer, String> torskMeetings = new HashMap<Integer, String>();

    for (Entry<Integer, String> entry : MONTHS.entrySet()) {
        if (entry.getValue().endsWith("r")) {
            torskMeetings.put(entry.getKey(), entry.getValue());
        }
    }
    
    logger.info(torskMeetings);
    
    assertThat(torskMeetings.values(), contains(
            "September", "October", "November", "December"));
}

Java 8

This example snippet will show how to filter a map by values using java 8. Using the powerful streams api, we will call entrySet.stream and filter values that end with "r" by creating a java.util.function.predicate using a lambda expression. Then using Collectors.toMap we will map each element in the stream back into a map.

@Test
public void filter_map_by_values_java8_lambda () {
    
    Map<Integer, String> torskMeetings = 
            MONTHS.entrySet()
            .stream()
            .filter(p -> p.getValue().endsWith("r"))
            .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
    
    logger.info(torskMeetings);
    
    assertThat(torskMeetings.values(), contains(
            "September", "October", "November", "December"));
}

Google Guava

The guava Maps collection utility provides Maps.filterValues which accepts a map and a guava predicate as parameters then returning a map containing the mappings whose values satisfy the predicate.

@Test
public void filter_map_by_values_guava () {

    Predicate<String> endsWithR = new Predicate<String>() {
        @Override
        public boolean apply(String input) {
            return input.endsWith("r");
        }
    };
    
    Map<Integer, String> torskMeetings = Maps.filterValues(MONTHS, endsWithR);
    
    logger.info(torskMeetings);
    
    assertThat(torskMeetings.values(), contains(
            "September", "October", "November", "December"));
}