Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to conditionally modify a Map in Java 8 stream API?

I am trying to modify a Map's keys based on conditional logic and struggling. I'm new to Java 8 streams API. Let's say I have a map like this:

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

map.put("PLACEHOLDER", "some_data1");
map.put("Google", "some_data2");
map.put("Facebook", "some_data3");
map.put("Microsoft", "some_data4");

When I would like to do is find the references of PLACEHOLDER and conditionally change that key to something else based on a boolean condition. I feel like it should be something like the below, but this doesn't even compile of course.

boolean condition = foo();

map = map.entrySet().stream().filter(entry -> "PLACEHOLDER".equals(entry.getKey()))
        .map(key -> {
            if (condition) {
                return "Apple";
            } else {
                return "Netflix";
            }
        }).collect(Collectors.toMap(e -> e.getKey(), Map.Entry::getValue));

I found this question which kind of makes me think maybe I can't do this with Java 8 stream APIs. Hopefully someone better at this than me knows how to do this. Ideone link if you want to play with it.

like image 787
boltup_im_coding Avatar asked Jul 22 '26 10:07

boltup_im_coding


2 Answers

You've filtered out all elements that aren't PLACEHOLDER. You need to add that filter logic to your map operation:

final Map<String, String> output = input.entrySet().stream()
        .map(e -> {
            if (!e.getKey().equals("PLACEHOLDER")) {
                return e;
            }
            if (condition) {
                return new AbstractMap.SimpleImmutableEntry<>("Apple", e.getValue());
            }
            return new AbstractMap.SimpleImmutableEntry<>("Netflix", e.getValue());
        }).collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

But as you are guaranteed to only have a single instance of PLACEHOLDER in the Map, you can just do

String placeholderData = input.remove("PLACEHOLDER");
if (placeholderData != null) {
    input.put(condition ? "Apple" : "Netflix", placeholderData);
}
like image 169
Boris the Spider Avatar answered Jul 23 '26 23:07

Boris the Spider


If you really want to do it using Streams, you just need to move the conditional logic to the collection phase, like that:

boolean condition = true;
map.entrySet().stream().collect(Collectors.toMap(
        entry -> mapKey(entry.getKey(), condition), Map.Entry::getValue
));

where:

private static String mapKey(String key, boolean condition) {
    if (!"PLACEHOLDER".equals(key)) {
        return key;
    }
    if (condition) {
        return "Apple";
    } else {
        return "Netflix";
    }
}

However, the second part of Boris the Spider's answer using Map.remove and Map.put seems the best way to go.

like image 41
Tomasz Linkowski Avatar answered Jul 23 '26 23:07

Tomasz Linkowski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!