经过数小时的研究,我找不到解决问题的方法。我有一个Map<String, List<User>>
,我想根据列表中的某些值删除地图中的某些项目。
我必须遵循User class
public class User {
public String firstName,
public Integer age
public boolean is50() {
return this.age.equals(50);
}
}
我有一个这样的地图:
Map<String, List<User> myMap = new HashMap<>();
myMap.put("A", new ArrayList<>());
myMap.get("A").add(new User("John", 50));
myMap.get("A").add(new User("Bob", 30));
myMap.put("B", new ArrayList<>());
myMap.get("B").add(new User("Sam", 25));
myMap.get("B").add(new User("Sarah", 56));
myMap.put("C", new ArrayList<>());
myMap.get("C").add(new User("Gill", 15));
myMap.get("C").add(new User("Jim", 20));
现在,如果列表年龄中至少有一个用户为50,我想删除Map的条目。此外,我想使用Java 8功能来实现。
我发现有一个removeIf
函数,但是我不能使其与列表一起使用。
我尝试过这样的事情:
Map<String, List<User> filteredMap = myMap
.enrySet()
.removeIf(e -> e.getValue()
.stream()
.filter(user -> user::is50)
.collect(Collectors.toList())
当然不行:(
例外的输出是一个过滤的地图,所有用户只有B键和C键(必须删除A键,因为John的年龄为50岁)
感谢您的帮助,希望一切都清楚;)
答案 0 :(得分:8)
这应该可以解决问题:
myMap.entrySet()
.removeIf(e -> e.getValue()
.stream()
.anyMatch(User::is50));
请注意,entrySet()的修改(removeIf)影响条目集支持的映射。因此,您必须制作地图的副本并在副本上运行它,或者修改第一个地图(myMap
)。
要制作地图副本,您只需执行以下操作:
Map<String, List<User>> copy = new HashMap<>(myMap);
编辑:
按照@Holger的建议,执行就地删除的更好方法如下:
myMap.values()
.removeIf(v -> v.stream()
.anyMatch(User::is50));
这更好的原因有四个:
getValue
的调用,因为values
直接提供了设置的值。values
和一个值之间的逻辑跳跃相比,entrySet
和一个值之间的逻辑跳跃要少。peek
却是反模式)。values
返回的集合是backed by the map。答案 1 :(得分:7)
只需将Stream::noneMatch
用于嵌套流:
Map<String, List<User>> filteredMap = myMap.entrySet()
.stream()
.filter(e -> e.getValue()
.stream()
.noneMatch(User::is50)
)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
filteredMap.forEach((key, value) -> System.out.println(key));
输出为:
B
C
在此解决方案中,myMap
不会受到影响,因为我使用了stream
中的entrySet
然后收集它。 Set::removeIf
会更改您以前的地图,因为Map::entrySet
返回了Set
个条目,这些条目支持您的原始Map
。
答案 2 :(得分:2)
您已经注意到,您必须在EntrySet上进行操作。您可以将其转换为流,然后像这样收集回新地图:
myMap.entrySet().stream()
.filter(e -> e.getValue().stream().noneMatch(User::is50))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
答案 3 :(得分:0)
您可以使用Map EntrySet来解析地图,然后解析每个条目中的列表
for (Map.Entry<String, List<User> entry : myMap.entrySet())
{
boolean toDelete = false;
for (User user : entry.getValue())
{
if (user.age == 50)
toDelete = true;
}
if (toDelete)
myMap.remove(entry.getKey());
}