2015-02-11 2 views
0

Рассмотрим следующий код:Исключение одновременной модификации. Как избежать этого сценария?

List tableData = null; 
tableData = new ArrayList(records.size()); 
for (Iterator iter = records.iterator(); iter.hasNext();) { 
      Test record = (Test) iter.next(); 
      Map rowData = createRowData(record); 
      if (rowData != null) { 
       // sorted insert 
       Date newDate = (Date)  rowData.get(TestModel.TIMESTAMP); 
       boolean done = false; 
       for (int row = 0; row < tableData.size(); row++) { 
        Map currentRow = (Map) tableData.get(row); 
        Date currentDate = (Date)  currentRow.get(TestModel.TIMESTAMP); 
        if (currentDate.after(newDate)) { 
         tableData.add(row, rowData); 
         done = true; 
         break; 
        } 
       } 
    if (!done) { 
        tableData.add(rowData); 
       } 
      } 
     } 
    } catch(Exception e) { 
     throw new RuntimeException("Error reading fuel and SMU data", e); 
    } 
    return tableData; 

records здесь являются new Vector(), который инициализируется между ними.

Поскольку ArrayList имеет аргумент вместимости int. Как я могу использовать CopyOnWriteArrayList в этом сценарии?

`STACKTRACE: 
    at com.mincom.explorer.uif.AbstractRequestHandler.handleException(AbstractRequestHandler.java:255) 
    at com.mincom.explorer.uif.AbstractRequestHandler.readData(AbstractRequestHandler.java:137) 
    at com.mincom.jive.service.RequestExecutor$RequestHandlerCommand.mainProcess(RequestExecutor.java:156) 
    at com.mincom.util.executor.AbstractCommand.run(AbstractCommand.java:56) 
    at com.mincom.util.executor.SimpleExecutor$WorkerThread.run(SimpleExecutor.java:156) 
THROWABLE: java.lang.RuntimeException: Error reading fuel and SMU data 
    at minestar.production.presentation.page.fuel.smu.assistant.*.getEventsUsingFilter(*.java:243) 
    at minestar.production.presentation.page.fuel.smu.assistant.*.processReadData(*.java:174) 
    at com.mincom.explorer.uif.AbstractRequestHandler.readData(AbstractRequestHandler.java:129) 
    at com.mincom.jive.service.RequestExecutor$RequestHandlerCommand.mainProcess(RequestExecutor.java:156) 
    at com.mincom.util.executor.AbstractCommand.run(AbstractCommand.java:56) 
    at com.mincom.util.executor.SimpleExecutor$WorkerThread.run(SimpleExecutor.java:156) 
Caused by: java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source) 
    at java.util.ArrayList$Itr.next(Unknown Source) 
    at *.production.presentation.page.fuel.smu.assistant.*.getEventsUsingFilter(*.java:222) 
    ... 5 more` 

Я снова модифицировал кусок кода. PLease посмотреть.

+1

Начните с объяснения, что именно делает исключение. –

+0

Этот вопрос полностью расплывчатый и неясный. Пожалуйста, укажите ** полный исходный пример **, а также ** полную ** исключение stacktrace 'ConcurrentModificationException', которое мы можем попробовать и скопировать, чтобы помочь вам точно. –

+0

@MarkoTopolnik Я отредактировал мой вопрос. – NewBie

ответ

0

Вы изменяете список, с которым работаете.

Есть два способа избавиться от этого. Один из них: создать копию своего фактического списка и перебрать этот новый список, но изменить старый.

List copy = copyOf(myArrayList); 
for(item : copy){ 
    //do stuff 
    //addon original list 
    myArrayList.add(item); 
} 

Во-вторых, повторите попытку по вашему списку.

for(int i = list.size()-1; i >=0; i--){ 
    //add or remove or do stuff here 
} 

Второе решение не будет работать для вас, поскольку вы добавляете свой товар по определенному индексу. Но если вы просто добавить/удалить текущий захваченный элемент, это было бы хорошо, тоже

Заметим, что это псевдо-код

+0

В коде нет доказательств того, что OP делает это. –

+0

'tableData = new ArrayList .....' -> 'for (int row = 0; row 'tableData.add ...' – Loki

+0

Действительно, я пропустил внутренний цикл. –

0

Вы итерация список массива, а затем изменить его, добавив tableData.add(row, rowData); данные на конкретного индекса, т.е. изменение размера списка.

Я думаю, что это является ведущим java.util.ConcurrentModificationException исключением, лучше создать другой список массивов и добавить в него контент.

0

Вы добавляете данные в List во время прохода через него:

for (int row = 0; row < tableData.size(); row++) { 
    Map currentRow = (Map) tableData.get(row); 
    Date currentDate = (Date)  currentRow.get(TestModel.TIMESTAMP); 
    if (currentDate.after(newDate)) { 
     tableData.add(row, rowData); 
     done = true; 
     break; 
    } 
} 

Это причина, почему вы получаете ConcurrentModificationException.

CopyOnWriteArrayList не решит вашу проблему: Я хотел бы предложить, чтобы клонировать ваши tableData и в то время как переборе Ваш оригинальный tableData, добавлять новые записи в clonedTableData, а затем назначить tableData к «равным» clonedtableData. Примечание: Это может быть дорогостоящее упражнение.

Причина, почему я сказал, что «CopyOnWriteArrayList не решит вашу проблему» основана на его дизайн:

Этот массив не меняется в течение жизни итератора, поэтому вмешательство невозможно, и итератору гарантированно не бросать ConcurrentModificationException. Итератор не отражает добавления, удаления или изменения, внесенных в список с момента его создания . Операции смены элементов на самих итераторах (remove, set и add) не поддерживаются. Эти методы бросают UnsupportedOperationException.

0

Не добавляйте данные в список, пока выполняете итерацию.

+0

Вид вас, но вы на самом деле не вносите ничего, чего еще нет в другом ответе. Я не думаю, что есть необходимость в повторение. –

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