列表映射的过滤器映射

时间:2021-07-10 15:32:24

标签: java java-stream

我有一个 HashMap 类型:

Map<String, Map<String, List<MyPojo>>> myMap;

MyPojo 有一个元素 String domain

在某些情况下,此域可以为空。

我想过滤我的地图,这样子地图 Map<String, List<MyPojo>> 都不应该有空域。

2 个答案:

答案 0 :(得分:3)

开场白:您可能不应该使用 Map<String, Map<String, List<MyPojo>>> - 这太复杂了。这里应该有更多的写出类型。也许是 Map<String, Students> 或类似的。你的问题没有说明你的问题域是什么,所以我只能说你的起始类型可能不是好的代码风格。

让我们来回答你的问题:

如果您的意思是在 j.u.Stream 的过滤器中使用 filter,那么您不能。 Map 接口没有 removeIf,流/过滤器的东西不是改变现有的类型,只是创造新的东西。任何修改底层映射的尝试都会导致 ConcurrentModificationExceptions。

这里是如何“就地”更改地图

var it = myMap.entrySet().iterator();
while (it.hasNext()) {
   if (it.next().getValue().values().stream()
     // we now have a stream of lists.
     .anyMatch(
       list -> list.stream().anyMatch(mp -> mp.getDomain() == null))) {
     it.remove();
    }
}

这里有一个嵌套的 anyMatch 操作:如果子图中的 any 条目包含一个列表,其中 any 条目包含该列表,则您想要删除 ak/v 对有一个空域。

让我们看看它的实际效果:

import java.util.*;
import java.util.stream.*;

@lombok.Value class MyPojo {
  String domain;
}

class Test { public static void main(String[] args) {
Map<String, Map<String, List<MyPojo>>> myMap = new HashMap<>();
myMap.put("A", Map.of("X", List.of(), "Y", List.of(new MyPojo(null))));
myMap.put("B", Map.of("V", List.of(), "W", List.of(new MyPojo("domain"))));

System.out.println(myMap);

var it = myMap.entrySet().iterator();
while (it.hasNext()) {
   if (it.next().getValue().values().stream()
     // we now have a stream of lists.
     .anyMatch(
       list -> list.stream().anyMatch(mp -> mp.getDomain() == null))) {
     it.remove();
    }
}

System.out.println(myMap);

}}

鉴于上述内容,生成新地图的代码并不难弄清楚。

答案 1 :(得分:1)

正如我在评论中提到的,不清楚(至少对我而言)是否希望映射在过滤后保留为空 ListMap,但如果您不这样做不关心空的 Maps/Lists 之后你可以使用:

map.values().stream().flatMap(v -> v.values().stream())
        .forEach(l -> l.removeIf(p -> p.getDomain() == null));
相关问题