2008-10-07

Comparing two collections


There is standard task when you have GUI table and database table, and you need to merge differences.
Most of people I know will do it like this:


Set source; // set of records from UI
Set target; // set of records in database
for (Object o : source) {
    // if we have object in source without
    // same object in target - it was added by user:
    if (!target.contains(o)) {
        target.add(o);
    }
}
Iterator iterator = target.iterator();
while (iterator.hasNext()) {
    Object o = iterator.next();
    // if we have object in target without
    // same object in source - it was removed by user:
    if (!source.contains(o)) {
        iterator.remove();
    }
}


We have 2 full collection iterations. In most cases it will not cause big performance issue. But it looks bad and will cause performance problems with slow Collection implementations or with big amounts of data.

After using my brain few minutes I found the best way of comparing, with only one iteration:


Set source; // set of records from UI
Set target; // set of records in database
// just checking:
if (target.equals(source)) {
    return;
}
Iterator iterator = target.iterator();
while (iterator.hasNext()) {
    Object o = iterator.next();
    if (source.contains(o)) {
        // remove all checked objects for future
        source.remove(o);
    }
    else {
        // if source does not contains object -
        // it was removed by user, removing it from target:
        iterator.remove();
    }
}
// all object left in source are added by user.
// Adding them to target:
target.addAll(source);


Simple enough, isn't it?