Search code examples
for-loopjava-8sonarqubejava-stream

Refactor the code in order to not assign to this loop counter from within the loop body - How to use stream insread of for loop


From SonarQube I get the issues: "Refactor the code in order to not assign to this loop counter from within the loop body." This issue is due to use of "i--". How can I do this with streams? I can not use HashSet, since it would remove all multiple Students from the list.

A list of all students is provided and in the list some specific student can be added multiple times on diferenet positions. Every student was added with Name and Surname or with Passport Id, but not both. With the code below I remove some specific student no matter how many times is this student in the list based on his Name and Surname or Passport id.

 for (int i = 0; i < listOfAllStudents.size(); i++) {
    if (removedStudent.getNameAndSurname() != null
        &&
         listOfAllStudents.get(i).getNameAndSurname() != null
         &&
         removedStudent.getNameAndSurname().equals(listOfAllStudents.get(i).getNameAndSurname())) 
        {
            listOfAllStudents.remove(i);
             i--;
         }
     if (removedStudent.getPassportId() != null
        &&
         listOfAllStudents.get(i).getPassportId() != null
         &&
         removedStudent.getPassportId().equals(listOfAllStudents.get(i).getPassportId())) 
        {
            listOfAllStudents.remove(i);
             i--;
         }  
 }

Solution

  • The code wants to update the original list once the criteria matches.The removal of an element for each iteration would be expensive in general, so relying on internal iterators and re-assigning the list variable with filtered list should workout well (assuming the said list is not final).

        private static List<Student> updateStudentList(List<Student> listOfAllStudents, Student removedStudent) {
            Predicate<Student> nameSurnameMatches = student-> student.getNameAndSurname()!=null
                                                            && Optional.of(student.getNameAndSurname())
                                                                .equals(Optional.ofNullable(removedStudent.getNameAndSurname()));
            Predicate<Student> passportIdMatches = student-> student.getPassportId()!=null
                                                            && Optional.of(student.getPassportId())
                                                            .equals(Optional.ofNullable(removedStudent.getPassportId()));
    
            listOfAllStudents = listOfAllStudents.stream()
                                                .filter(nameSurnameMatches)
                                                .filter(passportIdMatches)
                                                .collect(Collectors.toList());
            return listOfAllStudents;
        }