Stream and filter a SortedMap

1.4k Views Asked by At

I am sure this is straightforward but for some reason I am not getting what I want.

I have a SortedMap<String, String> values and I want to stream and filter through it and save only some values.

For example:

    SortedMap<String, String> input = new TreeMap<>();
    values.put("accepted.animal", "dog");
    values.put("accepted.bird", "owl");
    values.put("accepted.food", "broccoli");
    values.put("rejected.animal", "cat");
    values.put("rejected.bird", "eagle");
    values.put("rejected.food", "meat");

I only want to keep values that contain "accepted" in the key and drop everything else.

So, the result would be:

{accepted.animal=dog, accepted.bird=owl, accepted.food=broccoli}

How do I stream through the map and filter out everything except keys that contain "accepted"?

This is what I tried:

private SortedMap<String, String> process(final Input input) {
    final SortedMap<String, String> results = new TreeMap<>();

    return input.getInputParams()
                .entrySet()
                .stream()
                .filter(params -> params.getKey().contains("accepted"))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
} 

But it fails due to "Non-static method cannot be referenced from static context".

2

There are 2 best solutions below

4
Naman On BEST ANSWER

You need to use another variant of Collectors.toMap such that you pass the merge function and supplier to collect as a TreeMap there :

return input.getInputParams()
        .entrySet()
        .stream()
        .filter(params -> params.getKey().startsWith("accepted")) // small change
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                (a, b) -> b, TreeMap::new));
1
jaco0646 On

Ultimately, the method doesn't compile because Collectors.toMap() returns Map, whereas the method signature requires a return type of SortedMap.

I don't know the reason behind the misleading "static context" error message; but when I attempt to build the code with Gradle I get a slightly more helpful message.

error: incompatible types: inference variable R has incompatible bounds .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); ^ equality constraints: Map<K,U> lower bounds: SortedMap<String,String>,Object

You probably want the overloaded version of Collectors.toMap() that accepts a Supplier<Map>, so that you can provide a SortedMap for output.