I have a map of type Map<Object, Optional<String>>
. What is the most concise way to split this map into two lists. The first list should have a list of Objects, for which the Optional is present, and the second list should have a list of Objects, for which the Optional is not present.
I came up with that, but is there a better way:
List<Object> a = new ArrayList<>();
List<Object> b = new ArrayList<>();
myMap.forEach((obj, str) -> {
if (str.isEmpty()) {
a.add(obj);
} else {
b.add(obj);
}
});
CodePudding user response:
With streams this may look like this:
Map<Boolean,List<Object>> collect = myMap.entrySet().stream()
.collect(partitioningBy(e -> e.getValue().isPresent(),
mapping(e -> e.getKey(), toList())));
List<Object> a = collect.get(false);
List<Object> b = collect.get(true);
Not really more readable, but a more functional style.
CodePudding user response:
I would extract a method with filter logic.
public static void main(String[] args) {
Map<Object, Optional<String>> map = Map.of();
List<Object> empty = filterValueAndGetKeys(map, Optional::isEmpty);
List<Object> notEmpty = filterValueAndGetKeys(map, Optional::isPresent);
}
private static <T> List<T> filterValueAndGetKeys(Map<T, Optional<String>> map,
Predicate<Optional<String>> valueFilter) {
return map.entrySet().stream()
.filter(entry -> valueFilter.test(entry.getValue()))
.map(Map.Entry::getKey)
.collect(Collectors.toUnmodifiableList());
}