Partitioning a Map in Java 8+
You can have filtered map
by applying filtering on the original map
, e.g.:
List<String> list = new ArrayList<>(); //List of values
Map<String, String> map = new HashMap<>();
Map<String, String> filteredMap = map.entrySet()
.stream()
.filter(e -> list.contains(e.getKey()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
You can then compare the filteredMap
contents with original map
to extract the entries that are not present in the filteredMap
.
You can reduce each group using toMap
(as a downstream collector):
Map<String, String> myMap = new HashMap<>();
myMap.put("d", "D");
myMap.put("c", "C");
myMap.put("b", "B");
myMap.put("A", "A");
List<String> myList = Arrays.asList("a", "b", "c");
Map<Boolean, Map<String, String>> result = myMap.entrySet()
.stream()
.collect(Collectors.partitioningBy(
entry -> myList.contains(entry.getKey()),
Collectors.toMap(Entry::getKey, Entry::getValue)
)
);
And for this example, that produces {false={A=A, d=D}, true={b=B, c=C}}
Though partitioningBy
is the way to go when you need both the alternatives as an output based on the condition. Yet, another way out (useful for creating map based on a single condition) is to use Collectors.filtering
as :
Map<String, String> myMap = Map.of("d", "D","c", "C","b", "B","A", "A");
List<String> myList = List.of("a", "b", "c");
Predicate<String> condition = myList::contains;
Map<String, String> keysPresentInList = myMap.keySet()
.stream()
.collect(Collectors.filtering(condition,
Collectors.toMap(Function.identity(), myMap::get)));
Map<String, String> keysNotPresentInList = myMap.keySet()
.stream()
.collect(Collectors.filtering(Predicate.not(condition),
Collectors.toMap(Function.identity(), myMap::get)));
or alternatively, if you could update the existing map in-place, then you could retain entries based on their key's presence in the list using just a one-liner:
myMap.keySet().retainAll(myList);