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 .

7
  • Is this a single- or multithreaded application? And please give the StackTrace of the Exception. Commented Jan 12, 2014 at 14:47
  • the error here : processList = parse(item, DEFAULT_START_LEVEL); Commented Jan 12, 2014 at 14:59
  • at the moment i'm try to use listIterator Commented Jan 12, 2014 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) Commented Jan 12, 2014 at 15:06
  • Could you please update your question (with the edit button) with the content of findProcess()? Commented Jan 12, 2014 at 15:19

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

That's what I guess as well, but I can't find that in the code.
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.
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.
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())

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.