This is related to hibernate add-remove-update for collections. Read here about it
Set A = {R, G, B}
Set Z = {R, G, Y}
Final Set to the DB is = {R, G, Y}, well looks simple so we just send the second set Z, yeah but the catch is it needs to maintain the instance of A and finally send back A to the hibernate layer again, so all the manipulations happen on it.
Mathematically solving the problem, we need an intersection of A & Z {R, G} and a union of the relative complement of A & Z {R, G } + {Y} = {R, G , Y}
Using Java we can solve this using three approaches.
- For Loop
- CollectionUtils
- JDK collections native (1.6)
private static void forLoop(List<Set<String>> all) {
Setdb = all.get(0);
Setweb = all.get(1);
SettempCollection = new HashSet<String>();
tempCollection.addAll(db);
for (String t : tempCollection) {
if (!web.contains(t)) {
db.remove(t);
}
}
for (String t : web) {
if (!tempCollection.contains(t)) {
db.add(t);
}
}
}
CollectionUtils
private static void collectionUtils(List<Set><String>> all) {
Set db = all.get(0);
Set web = all.get(1);
CollectionUtils.retainAll(web, db);
db.addAll(web);
}
JDK Collection Native
private static void jdkNative(List<Set><String>> all) {
Set db = all.get(0);
Set web = all.get(1);
db.retainAll(web);
db.addAll(web);
}
Now we ran a performance test on both, and were shocked to see the results.
- forLoop -18 ms
- collectionUtils -72 ms
- jdkNative -5 ms
Create Collections
private static List<Set<String>> createCollections() {
List<Set<String>> all = new ArrayList<Set<String>>();
Set<String> db = new HashSet<String>();
Set<String> web = new HashSet<String>();
for (int i = 0; i < 10000; i++) {
db.add(String.valueOf(i));
}
for (int i = 5000; i < 15000; i++) {
web.add(String.valueOf(i));
}
all.add(db);
all.add(web);
return all;
}
and the main method
public static void main(String[] args) {
long start = 0;
long end = 0;
List<Set<String>> all = createCollections();
start = new Date().getTime();
forLoop(all);
end = new Date().getTime();
System.out.println("TIME BY forLoop " + (end - start));
start = new Date().getTime();
jdkNative(all);
end = new Date().getTime();
System.out.println("TIME BY jdkNative " + (end - start));
start = new Date().getTime();
collectionUtils(all);
end = new Date().getTime();
System.out.println("TIME BY collectionUtils " + (end - start));
}
So avoid using the CollectionUtils. See what is more important, cleaner code or faster code ;)