I have a map to iterate, and I want to check the values of entryset with two conditions; if meet condition 1, I group it into a collection, findFirst()
and get the Optional<>
, if not, filter with another condition and collect to another collection, do the same.
I did with for
loops in one iteration. Now, if I want to iterate only once with Java 8 stream, is it possible?
I have tried with stream().filter(cond1).map(Map.Entry::getValue).findFirst()
(iterate twice).
I also checked groupingBy()
and partitionBy()
but I haven't seen the possibility yet.
Example of approach 1:
for (Map.Entry<String, Response> entry: responses.entrySet()) {
String key = entry.getKey();
Response value = entry.getValue();
if (key.equals("foo") && !value.equals("bar")) {
res1 = value;
} else if (key.equals("some other key")) {
res2 = value;
}
}
Response finalResponse = res1 != null ? res1 : res2;
Example of approach 2:
Optional<Response> res1 = Optional.empty();
Response res2;
res1 = responses.entrySet().stream()
.filter(entry -> entry.getKey().equals("foo") &&
!entry.getValue().equals("bar"))
.map(Map.Entry::getValue)
.findFirst();
res2 = responses.entrySet().stream()
.filter(entry -> entry.getKey().equals("some other key"))
.map(Map.Entry::getValue)
.findFirst().orElse(null);
Response finalResponse = res1.orElse(res2);
If your condition is just based on .equals()
on a key and value, like you are showing in your question, you can just use map.get()
and a simple if
statement:
Response result = responses.get("foo");
if (result == null || result.equals(bar))
result = responses.get("some other key");
So there is no need to use anything else.
Or as Holger suggested you may alternatively use map.getOrDefault()
:
Response result = responses.getOrDefault("foo", bar);
if(result.equals(bar))
result = responses.get("some other key");