列表地图的过滤地图
Filter Map of Map of List
我有一个 HashMap 类型:
Map<String, Map<String, List<MyPojo>>> myMap;
MyPojo
有一个元素 String domain
.
在某些情况下,此域可以为空。
我想过滤我的地图,以便子地图 Map<String, List<MyPojo>>
的 none 应该有空域。
开场白:您可能不应该 Map<String, Map<String, List<MyPojo>>>
- 这太复杂了。这里应该有更多写出来的类型。也许是 Map<String, Students>
之类的。你的问题没有说清楚你的问题域是什么,所以我只能说你的起始类型可能不是好的代码风格。
让我们来回答您的问题:
如果您在 j.u.Stream 的过滤器中指的是 filter
,那么您不能。 Map
接口没有 removeIf
,并且 stream/filter 的东西不是关于改变现有的类型,只是关于制作新的东西。任何修改底层映射的尝试只会让您遇到 ConcurrentModificationExceptions。
这是更改地图的方法'in place'
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 条目包含 [=31] 的列表,则您想删除 k/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);
}}
鉴于上述情况,生成新地图的代码并不难理解。
正如我在评论中提到的那样,不清楚(至少对我而言)您是否希望在过滤后为空 List
s 或 Map
s 保留映射,但是如果你不关心空 Map
s/List
s 之后你可以使用:
map.values().stream().flatMap(v -> v.values().stream())
.forEach(l -> l.removeIf(p -> p.getDomain() == null));
我有一个 HashMap 类型:
Map<String, Map<String, List<MyPojo>>> myMap;
MyPojo
有一个元素 String domain
.
在某些情况下,此域可以为空。
我想过滤我的地图,以便子地图 Map<String, List<MyPojo>>
的 none 应该有空域。
开场白:您可能不应该 Map<String, Map<String, List<MyPojo>>>
- 这太复杂了。这里应该有更多写出来的类型。也许是 Map<String, Students>
之类的。你的问题没有说清楚你的问题域是什么,所以我只能说你的起始类型可能不是好的代码风格。
让我们来回答您的问题:
如果您在 j.u.Stream 的过滤器中指的是 filter
,那么您不能。 Map
接口没有 removeIf
,并且 stream/filter 的东西不是关于改变现有的类型,只是关于制作新的东西。任何修改底层映射的尝试只会让您遇到 ConcurrentModificationExceptions。
这是更改地图的方法'in place'
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 条目包含 [=31] 的列表,则您想删除 k/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);
}}
鉴于上述情况,生成新地图的代码并不难理解。
正如我在评论中提到的那样,不清楚(至少对我而言)您是否希望在过滤后为空 List
s 或 Map
s 保留映射,但是如果你不关心空 Map
s/List
s 之后你可以使用:
map.values().stream().flatMap(v -> v.values().stream())
.forEach(l -> l.removeIf(p -> p.getDomain() == null));