【问题标题】:Nested forEach in Java 8 throws an exception [duplicate]Java 8中的嵌套forEach引发异常[重复]
【发布时间】:2019-02-26 08:26:53
【问题描述】:

编辑 它的工作

        group.getUsers().forEach(user -> {
        user.removeGroup(group);
        privilegeRepository.findAll().stream().
                filter(privilege -> privilege.getName().startsWith(slugname.toUpperCase()))
                .forEach(privilege -> {
            user.removePrivilege(privilege);
            privilegeRepository.delete(privilege);
        });
    });

我有嵌套的 for 循环,我想用 forEach 替换那个 for 循环:

for (User user : group.getUsers()) {
     user.removeGroup(group);

     for(Privilege privilege : user.getPrivileges()){

         if (privilege.getName().startsWith(slugname.toUpperCase())){
             user.removePrivilege(privilege);
             privilegeRepository.delete(privilege);
         }
     }
}

group.getUsers().forEach(user -> {

     user.removeGroup(group);

     user.getPrivileges().stream().filter(privilege -> privilege.getName().startsWith(slugname.toUpperCase()))
          .forEach(privilege -> {
              user.removePrivilege(privilege);
              privilegeRepository.delete(privilege);
          });
});

它会抛出一个异常:

java.util.ConcurrentModificationException

【问题讨论】:

  • 完整的堆栈跟踪会很有用,所以我们可以看到哪一行抛出了异常
  • user.getPrivileges() vs privilegeRepository.findAll(): 看起来两者做的不一样
  • 这里不使用流,使用老式迭代器可能更有意义,您可以调用 remove() 来从用户权限中删除权限。
  • 在迭代 user.getPrivileges 时不能调用 user.removePrivilege。您需要制作快照副本以进行迭代。
  • 有趣的是为什么在第一个示例中没有得到java.util.ConcurrentModificationException(使用嵌套的for循环)。我认为user.removePrivilege(privilege); 仍然可以同时对您正在迭代的集合进行修改。

标签: java java-8


【解决方案1】:

这就是它所说的。在循环中,您正在修改您正在循环的数组,这在 Java foreach 循环中是不允许的。

我建议您在外部 foreach 循环(循环用户的位置)中为权限创建一个临时数组,并从该数组中删除项目,而不是用户的权限数组。因此,您应该使用 temp.remove(privilege) 之类的东西,而不是 user.removePrivilege(privilege);

内循环后,可以清空用户的权限数组,添加临时数组中的项。

【讨论】:

  • 所以在这种情况下不需要用 forEach 替换 for 循环?
  • 不,你可以保留forEach
  • @zblash for 循环有完全相同的问题。使用 Stream 时迭代策略不会改变,因此您使用的集合在迭代时不允许修改,如果您之前没有遇到异常,这纯属巧合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
  • 2016-05-30
  • 2014-06-03
  • 2015-04-06
  • 1970-01-01
相关资源
最近更新 更多