2010-05-13 3 views
-1

я пишу следующий код, но при этом работать он генерирует ConcurrentModificationExceptionConcurrentModificationException HashMap в Java

if(attendancePolicy.getType().equals(AttendanceConstants.EMPLOYEE_ATTENDANCE_POLICY)) { 
    synchronized(attendancePolicy.getListEmployee()) { 
     for(EmployeeAttendancePolicy employeeAttendancePolicy : attendancePolicy.getListEmployee()) { 
      employeeInfo = employeeInfoSessionBeanLocal.findEmployeeInfoEntityByEmployeeInfoId( 
        employeeAttendancePolicy.getEmployeeId()); 

      if(employeeInfo != null) { 
       employeeAttendancePolicy.setEmpName( 
         employeeInfo.getFirstName() + " " 
         + employeeInfo.getMiddleName() + " " 
         + employeeInfo.getLastName()); 

       company = companySessionBeanLocal.findCompanyById(employeeInfo.getCompanyId()); 
       employeeAttendancePolicy.setCompanyName(company.getName()); 

       department = departmentSessionBeanLocal.findDepartmentEntityByDepartmentId( 
         employeeInfo.getDepartmentId()); 
       employeeAttendancePolicy.setDepartmentName(department.getName()); 
      } 
      else { 
       attendancePolicy.getListEmployee().remove(employeeAttendancePolicy); 
      } 
     } 
    } 
} 
+1

Возможный дубликат [Итерирование в коллекции, исключая ConcurrentModificationException при удалении в цикле] (http://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re) – Raedwald

ответ

1

ConcurrentModificationException вызвано тем, что вы используете Iterator над List, и вы затем изменить что List.

Смотрите страницу Iterator Java DOC - http://java.sun.com/j2se/1.4.2/docs/api/java/util/Iterator.html, вы можете использовать remove метод Iterator, чтобы избежать этого:

Удаляет из основной коллекции последний элемент, возвращенный итератора (дополнительная работа) , Этот метод можно вызывать только один раз за звонок для следующего. Поведение итератора не указывается, если базовая коллекция модифицирована , в то время как итерация выполняется в любым способом, кроме как путем вызова этого метода .

Перепишите код для этого:

if(attendancePolicy.getType().equals(AttendanceConstants.EMPLOYEE_ATTENDANCE_POLICY)) { 
    synchronized(attendancePolicy.getListEmployee()) { 

     // Explicitly create the Iterator and loop condition 
     for(Iterator<EmployeeAttendancePolicy> it = 
attendancePolicy.getListEmployee().iterator(); it.hasNext();) { 

      // Explicitly declare the looping variable 
      EmployeeAttendancePolicy employeeAttendancePolicy = it.next(); 

      employeeInfo = employeeInfoSessionBeanLocal.findEmployeeInfoEntityByEmployeeInfoId( 
        employeeAttendancePolicy.getEmployeeId()); 

      if(employeeInfo != null) { 
       employeeAttendancePolicy.setEmpName( 
         employeeInfo.getFirstName() + " " 
         + employeeInfo.getMiddleName() + " " 
         + employeeInfo.getLastName()); 

       company = companySessionBeanLocal.findCompanyById(employeeInfo.getCompanyId()); 
       employeeAttendancePolicy.setCompanyName(company.getName()); 

       department = departmentSessionBeanLocal.findDepartmentEntityByDepartmentId( 
         employeeInfo.getDepartmentId()); 
       employeeAttendancePolicy.setDepartmentName(department.getName()); 
      } 
      else { 

       // Use the Iterator's remove method to safely remove 
       // thus avoiding the ConcurrentModificationException 
       it.remove(); 

      } 
     } 
    } 
} 
2

Вы удаления employeeAttendancePolicy от сотрудника списка внутри для цикла, который Перебор коллекции список сотрудников. Это «параллельная» операция, вызвавшая исключение.

Если вы хотите удалить что-либо из цикла, вам нужно вернуться к «регулярному» циклу итератора (а не к «расширенному» циклу выше). Что-то вроде этого возможно:

Iterator<EmployeeAttendancePolicy> iter = attendancePolicy.getListEmployee(); 
while (iter.hasNext()) 
{ 
    EmployeeAttendancePolicy employeeAttendancePolicy = iter.next(); 

    //... somewhere in here when you decide to remove 
    iter.remove(); 
} 
0

Вы удаляете элемент из списка, который вы итерируете.

Один из способов решения этого вопроса - добавить элемент для удаления в новую коллекцию, а затем, когда вы завершили первый цикл, удалите эти элементы из списка.

например. что-то вроде

 synchronized (attendancePolicy.getListEmployee()) { 
      Set toRemove = new HashSet(); 

      for(EmployeeAttendancePolicy employeeAttendancePolicy : attendancePolicy.getListEmployee()){ 

       employeeInfo=employeeInfoSessionBeanLocal.findEmployeeInfoEntityByEmployeeInfoId(employeeAttendancePolicy.getEmployeeId()); 

       if(employeeInfo!=null){ 
        ... 
       }else{ 
        toRemove.add(employeeAttendancePolicy); 
       } 

      } 
      attendancePolicy.getListEmployee().removeAll(toRemove); 
     } 
0

Посмотрите на ConcurrentHashMap и CopyOnWriteArrayList. Эти коллекции предназначены для использования, когда несколько потоков работают с коллекциями.

Смежные вопросы