Java Map, filter with values properties

16,212

Solution 1

You can use filters from Guava and the Predicate interface.

Predicate<T> yourFilter = new Predicate<T>() {
    public boolean apply(T o) {
        // your filter
    }
};

So, simple example would be:

Predicate<Integer> evenFilter = new Predicate<Integer>() {
    public boolean apply(Integer i) {
        return (i % 2 == 0);
    }
};

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

Map<Integer, Integer> evenMap = Maps.filterValues(map, evenFilter);

Solution 2

Rather than force your client code to use a filter/loop, build what you need into the API of your class:

public class MyClass {

    private TreeMap resMap new TreeMap<String, Map<String, String>>();

    public void filter(String key, String value) {
        // Some impl here. Either your loop or the guava approach
    }
}

BTW, if you use your loop, consider changing to this:

for (Iterator<Map.Entry<String, TreeMap<String, String>>> i = resMap.entrySet().iterator(); i.hasNext();) {
    Map.Entry<String, TreeMap<String, String>> entry = i.next();
    if (value.equals(entry.getValue().get(key))) {
        i.remove();
    }
}

The changes to the loop are:

  • Changed order of equals to avoid NPE
  • Using iterator to allow removal of entries directly

Even if you don't have a class, you could easily wrap it up in a static method on a utility class, where it could also easily be parameterized to work with any nested map:

public static <K1, K2, V> void filter(Map<K1, Map<K2, V>> map, K2 key, V value) {
    // Some impl here
}

Here's a non-guava impl for the static method:

for (Iterator<Map.Entry<K1, Map<K2, V>>> i = map.entrySet().iterator(); i.hasNext();) {
    Map.Entry<K1, Map<K2, V>> entry = i.next();
    if (value.equals(entry.getValue().get(key))) {
        i.remove();
    }
}
Share:
16,212
Admin
Author by

Admin

Updated on June 15, 2022

Comments

  • Admin
    Admin almost 2 years

    I have a

    TreeMap resMap new TreeMap<String, Map<String, String>>(); 
    

    I would like to filter and keep only entries that values contains a known pair, let's say ('mike' => 'jordan'), and avoid a loop like below

    Is there in my included libraries apache.commons and google.common a filter method (that probably would do a loop too, but at least it's less verbose

    for (Entry<String, TreeMap<String, String>> el : resMap.entrySet()){
        if (el.getValue().get("mike").equals("jordan")){
            //
        }
    }