0

EDIT its worked

        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);
        });
    });

I have nested for-loops and I want to replace that for-loops with a forEach:

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);
         }
     }
}

to

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);
          });
});

And it throws a exception:

java.util.ConcurrentModificationException

7
  • the complete stack trace would be useful, so we can see what line throw the exception Commented Feb 26, 2019 at 8:28
  • 1
    user.getPrivileges() vs privilegeRepository.findAll(): doesn't look like the two are doing the same thing Commented Feb 26, 2019 at 8:29
  • 2
    Instead of using streams here it might make more sense to use an old fashioned iterator which you can call remove() on to get the privilege removed from the user's privileges. Commented Feb 26, 2019 at 8:31
  • 1
    You cannot call user.removePrivilege while iterating over user.getPrivileges. You need to make a snapshot copy to iterate over. Commented Feb 26, 2019 at 8:32
  • 1
    It is interesting why you do not get java.util.ConcurrentModificationException in the first example (with the nested for-loops). I think user.removePrivilege(privilege); still can make modification on the collection that you are iterating in the same time. Commented Feb 26, 2019 at 8:52

1 Answer 1

0

It is what it says. In the loop, you are modifying the array you are looping through, which is not allowed in Java foreach loops.

I'd suggest you create a temporary array in the outer foreach loop (where you loop the users) for the privileges and delete the items from that array, instead of the user's privilege array. So instead of user.removePrivilege(privilege); you should use something like temp.remove(privilege).

After the inner loop, you can clear the user's privilege array and add the items in the temporary array.

Sign up to request clarification or add additional context in comments.

3 Comments

So in this case no need replace for-loops with a forEach ?
no, you can keep the forEach
@zblash the for-loops have exactly the same problem. The iteration policy does not change when you use a Stream, so you’re using a collection not allowing modifications while iterating and it’s a pure coincidence if you did not hit the exception previously.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.