2

I'm trying to find the first and newest object in an arraylist. These objects map directly to mongo documents.

The first object I can find easily by checking the _parentid field, which should be null, done, that's working.

The newest object is slightly trickier though, as it involves sorting timestamps(longs) and returning the latest.

The code I have is actually doing the job - proven by the console logs, but, I get an error on the last go of the for loop.

java.util.ConcurrentModificationException

Here is my code;

    public String aggregateRecords(List <VehicleRegistration> records) {

    VehicleRegistration parent;
    VehicleRegistration latest;

    //Parent = record without a parent id
    for (Iterator<VehicleRegistration> iterator = records.iterator(); iterator.hasNext(); ) {
        VehicleRegistration record = iterator.next(); <---errors here
        if (record._parentid == null) {
            parent = record;
            System.out.println("parent="+parent);
            iterator.remove();
        }
        //find latest child by timestamp
        else {
            records.sort(new Comparator<VehicleRegistration>() {
                @Override
                public int compare(VehicleRegistration v1, VehicleRegistration v2) {
                    return v1.timestamp.compareTo(v2.timestamp);
                }
            });
            Collections.reverse(records);
            System.out.println("sorted list="+records);
            latest = records.get(0);
            System.out.println("latest record="+latest);
        }
    }

    //todo - merge together and return
    return "this will be the aggregated record";
}
Kaigo
  • 1,267
  • 2
  • 14
  • 33
  • At which line do you get the error ? – Arnaud Jul 12 '18 at 12:48
  • just under the for loop, I put a flag in the code block. thanks – Kaigo Jul 12 '18 at 12:49
  • `Iterator` wont allow traversing as well as removal (at same time) on any `Collection`. So you can use a `ListIterator` – Arun Sudhakaran Jul 12 '18 at 12:52
  • Please refer to the explanation in this [answer](https://stackoverflow.com/a/223929) regarding why you are getting the [exception](https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html). Essentially, [Collections.reverse()](https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#reverse(java.util.List)) will *mess* with element order of the collection *while* you have an iterator open, hence the fail-safe exception you are seeing. – Saïd Jul 12 '18 at 12:57
  • The answer looks the same as what I'm doing, am I missing something? – Kaigo Jul 12 '18 at 13:04
  • Array != ArrayList ! – Pieter De Bie Jul 12 '18 at 13:15

1 Answers1

2

You are sorting the collection while you are iterating over it.

The else block is modifying the list on the following lines:

records.sort(new Comparator<VehicleRegistration>() {
    @Override
    public int compare(VehicleRegistration v1, VehicleRegistration v2) {
        return v1.timestamp.compareTo(v2.timestamp);
    }
});
Collections.reverse(records);

This sorts the list twice and will trigger a ConcurrentModificationException on the next call to iterator.next()

Aaron
  • 5,931
  • 4
  • 27
  • 31