0

I need help for this case below : I have 2 method :

private void calculateTime(Map.Entry<List<String>, List<LogRecord>> entry, List<LogProcess> processList) {
    List<List<LogRecord>> processSpentTime = new ArrayList<List<LogRecord>>();
    processSpentTime = subListProcess(entry, processSpentTime);
    for (List<LogRecord> item : processSpentTime) {
        processList = parse(item, DEFAULT_START_LEVEL);
    }
}

and the second method

private List<LogProcess> parse(List<LogRecord> recordList, int level) {
    List<LogProcess> processList = new ArrayList<LogProcess>();
    if(!recordList.isEmpty()) {
        LogProcess process = findProcess(recordList, level);
        if(!(process instanceof NullLogProcess)) {
            if(!(process instanceof IncompleteLogProcess)) {
                processList.add(process);
            }

            int fromIndex = recordList.indexOf(process.returnStartIndexOfNextProcess()) + 1;
            processList.addAll(parse(recordList.subList(fromIndex, recordList.size()), level));
        }
    }
    return processList;
}

public LogProcess findProcess(List<LogRecord> recordList, int level) {
    LogRecord endRecord = null;
    LogRecord startRecord = findStartRecord(recordList);
    if(startRecord instanceof NullLogRecord) {
        return new NullLogProcess();
    }       

    List<LogRecord> startEndRecord = findStartEndRecord(startRecord, recordList);
    startRecord = startEndRecord.get(0);
    endRecord = startEndRecord.get(1);

    LogProcess process = returnLogProcess(startRecord, endRecord);
    process.setLevel(level);
    process.setChildren(findChildProcess(recordList, startRecord, endRecord, level + 1));

    return process;
}

private List<LogProcess> findChildProcess(List<LogRecord> recordList, LogRecord startRecord, LogRecord endRecord, int level) {
    int fromIndex = recordList.indexOf(startRecord) + 1;
    int toIndex = recordList.indexOf(endRecord);
    if(toIndex > fromIndex) {
        List<LogRecord> recordSubList = recordList.subList(fromIndex, toIndex);
        return parse(recordSubList, level);
    } else  {
        return new ArrayList<LogProcess>();
    }
}

private List<LogRecord> findStartEndRecord(LogRecord startRecord, List<LogRecord> recordList) {
    List<LogRecord> startEndRecord = new ArrayList<LogRecord>();
    if (!recordList.isEmpty()) {
        startEndRecord.add(startRecord);
        for (LogRecord record : recordList) {

            boolean isStartRecord = record.isStartPoint() && record.hasSameActionName(startRecord);
            if(isStartRecord){
                startEndRecord = new ArrayList<LogRecord>();;
                startEndRecord.add(record);
                continue;
            }

            boolean isEndRecord = record.isEndPoint() && record.hasSameActionName(startRecord);
            if (isEndRecord) {
                startEndRecord.add(record);
                return startEndRecord;
            }

        }
        return startEndRecord;
    }
    return startEndRecord;
}

private LogRecord findStartRecord(List<LogRecord> recordList) {
    for (LogRecord record : recordList) {
        if (record.isStartPoint()){
            recordList.remove(record);
            return record;
        }
    }
    return new NullLogRecord();
}

at the method calculatime in the for loop I just get the result for the first item, and after that I got error the same the title . please help me and explain me more for this case .

Hien Vu
  • 45
  • 1
  • 1
  • 7
  • Is this a single- or multithreaded application? And please give the StackTrace of the Exception. – Markus Malkusch Jan 12 '14 at 14:47
  • the error here : processList = parse(item, DEFAULT_START_LEVEL); – Hien Vu Jan 12 '14 at 14:59
  • at the moment i'm try to use listIterator – Hien Vu Jan 12 '14 at 15:00
  • java.util.ConcurrentModificationException at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1129) at java.util.ArrayList$SubList.size(ArrayList.java:958) at java.util.AbstractCollection.isEmpty(AbstractCollection.java:86) at ch.soreco.alag.tool.analyze.LogProcessParser.parse(LogProcessParser.java:179) at ch.soreco.alag.tool.analyze.LogProcessParser.calculateTime(LogProcessParser.java:66) – Hien Vu Jan 12 '14 at 15:06
  • Could you please update your question (with the edit button) with the content of `findProcess()`? – Markus Malkusch Jan 12 '14 at 15:19
  • This is an issue with the foreach loop in java. please check this SO thread to solve your issue.. http://stackoverflow.com/questions/9806421/concurrentmodificationexception-when-adding-inside-a-for-each-loop-in-arraylist – dinukadev Jan 12 '14 at 15:43
  • yes. thanks Markus .i updated – Hien Vu Jan 12 '14 at 16:26

3 Answers3

2

The name of this exception is a bit confusing, because it isn't related to multi threading.

What happens is that you are iterating over a collection which is being modified while you are iterating over it.

If performance is not your highest concern, a simple way out would be to copy the list and iterate over that copy and add items to the original list.

pveentjer
  • 10,545
  • 3
  • 23
  • 40
  • That's what I guess as well, but I can't find that in the code. – Markus Malkusch Jan 12 '14 at 14:45
  • Can you post the whole stacktrace. At the moment the ConcurrentModEx is thrown, you know which line of code it was done on and then you can see which of your java structures is used there. – pveentjer Jan 12 '14 at 14:47
  • Although the name is confusing it can be related to multi threading because the exception also happens when another thread modifies the collection you iterate over. – zapl Jan 12 '14 at 14:49
0

My guess is it's related to recordList.subList():

Returns a view of the portion of this list. [..] The returned list is backed by this list. [..] The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list. [..] All methods first check to see if the actual modCount of the backing list is equal to its expected value, and throw a ConcurrentModificationException if it is not.

I don't see any modification, so it probably happens in findProcess(). Consider creating a copy of that list:

new ArrayList(recordList.subList())
Markus Malkusch
  • 7,738
  • 2
  • 38
  • 67
0

You are getting the exception because of this :

for (LogRecord record : recordList) {
        if (record.isStartPoint()){
            recordList.remove(record);    <--- This is the cause
            return record;
        }
}

Use an Iterator Instead

Iterator<LogRecord> iterator = recordList.iterator();
while(iterator.hasNext()){
    LogRecord logRecord = iterator.next();
    if(record.isStartPoint()){
        iterator.remove();
        return logRecord;
   }

Check if this works

jits
  • 1
  • 1