开发者

concurrentmodificationexception hashmap in java

I write following code but when this run it generate concurrentmodificationexception

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 = departmen开发者_开发问答tSessionBeanLocal.findDepartmentEntityByDepartmentId( 
                        employeeInfo.getDepartmentId() );
                employeeAttendancePolicy.setDepartmentName( department.getName() );
            }
            else {
                attendancePolicy.getListEmployee().remove( employeeAttendancePolicy );
            }
        }
    }
}


You're removing employeeAttendancePolicy from the list employee from within a for-loop that is iterating over the list employee collection. That is the "concurrent" operation that has caused the exception.

If you want to remove something from inside a loop, you need to revert to a "regular" iterator loop (not the "enhanced" for loop above). Something like this perhaps:

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

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


The ConcurrentModificationException is caused by the fact that you are using an Iterator over a List, and you are then modifying that List.

See the Iterator Java doc page - http://java.sun.com/j2se/1.4.2/docs/api/java/util/Iterator.html, you could use the remove method of the Iterator to avoid this:

Removes from the underlying collection the last element returned by the iterator (optional operation). This method can be called only once per call to next. The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.

Rewrite your code to this:

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

            }
        }
    }
}


You are removing an item from the list you are iterating over.

One way to resolve this is to add the item to remove to a new collection, and then, when you have completed the first loop, remove those items from the list.

e.g. something like

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


Take a look at ConcurrentHashMap and CopyOnWriteArrayList. These collections are designed to be used when multiple thread are working on collections.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜