为了账号安全,请及时绑定邮箱和手机立即绑定

删除 Map<Long, List<Object>> 的条目

删除 Map<Long, List<Object>> 的条目

青春有我 2023-06-14 13:58:48
经过数小时的研究,我找不到问题的解决方案。我有一个Map<String, List<User>>,我想根据列表中的某些值删除地图的某些项目。我必须关注用户类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())当然那是行不通的:(例外的输出是一个 filteredMap,所有用户只有 B 和 C 键(必须删除 A 键,因为 John 已经 50 岁了)谢谢你的帮助,希望它是清楚的;)
查看完整描述

4 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

这应该可以解决问题:

myMap.entrySet()
    .removeIf(e -> e.getValue()
        .stream()
        .anyMatch(User::is50));

请注意,entrySet() 修改 (removeIf) 会影响条目集支持的映射。因此,您要么必须制作地图的副本并在副本上运行它,要么让第一个地图 ( myMap) 被修改。

至于制作地图副本,您可以简单地执行以下操作:

Map<String, List<User>> copy = new HashMap<>(myMap);

就地删除的更好方法如下:

myMap.values()
    .removeIf(v -> v.stream()
        .anyMatch(User::is50));

这更好的原因有四个:

  1. getValue您可以取消对since 的调用,因为values它直接提供了值集。

  2. values它更清楚地传达意图 -与价值之间的逻辑跳跃比entrySet与价值之间的逻辑跳跃更少。

  3. 它更简洁并且不是反模式(例如,使用peekoutside of debugging 是一种反模式,尽管有时更简洁)。

  4. 它仍然有效,因为返回的 Collection由 mapvalues支持。


查看完整回答
反对 回复 2023-06-14
?
德玛西亚99

TA贡献1770条经验 获得超3个赞

只需用于Stream::noneMatch您的嵌套 Stream :


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返回。SetMap


查看完整回答
反对 回复 2023-06-14
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

如您所见,您必须对 EntrySet 进行操作。您可以将其转换为流并收集回新地图,如下所示:

myMap.entrySet().stream()
             .filter(e -> e.getValue().stream().noneMatch(User::is50))
             .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))


查看完整回答
反对 回复 2023-06-14
?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

您可以使用 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());

}


查看完整回答
反对 回复 2023-06-14
  • 4 回答
  • 0 关注
  • 122 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信