在 Java 8+ 中对映射进行分区

2022-09-01 18:18:12

我有一个和一个.我想根据条件对Map<String, String>List<String>Map

foreach(map.key -> list.contains(map.key))

并产生两个(s)。最优雅的方法是什么?我在Java 11上,所以你可以在答案中抛出你想要的一切。Map

我现在想到的是:

map.entrySet()
   .stream()
   .collect(partitioningBy(e -> list.contains(o.getKey())));

但这给出了一个.Map<Boolean, List<Entry<String, String>>>


答案 1

您可以使用(作为下游收集器)来减少每个组:toMap

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)
                    )
        );

对于这个例子,这会产生{false={A=A, d=D}, true={b=B, c=C}}


答案 2

虽然是当你需要两个替代方案作为基于条件的输出时要走的路。然而,另一种出路(对于基于单个条件创建地图很有用)是用作:partitioningByCollectors.filtering

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)));

或者,如果您可以就地更新现有地图,则可以仅使用一行即可根据其键在列表中的存在来保留条目:

myMap.keySet().retainAll(myList);

推荐