Compare two lists for updates, deletions and additions
Simple question.
I have a new list and an old list. In Java is there a standard way/library that allows me to compare these two lists and determine which items have been updated/deleted or are completely new? E.g. I should end up with three lists - Deleted items (items in old bu开发者_C百科t not in new), Updated items (items in both), New items (items in new and not in old).
I could write this myself but was wondering if there is a standard way to do it.
The objects in the list implement equals correctly.
No standard way sorry. You can do it fairly easily with the standard JDK without resorting to adding a dependency on Apache Commons (as others have suggested) however. Assuming your lists are List<T>
instances:
List<T> oldList = ...
List<T> newList= ...
List<T> removed = new ArrayList<T>(oldList);
removed.removeAll(newList);
List<T> same = new ArrayList<T>(oldList);
same.retainAll(newList);
List<T> added = new ArrayList<T>(newList);
added.removeAll(oldList);
There's nothing in the standard libraries.
However the Apache Commons CollectionUtils class gives you this functionality with the intersection and subtract methods:
Collection<T> old = ...;
Collection<T> neww = ...;
Collection<T> deleted = (Collection<T>)CollectionUtils.subtract(old, new);
Collection<T> updated = (Collection<T>)CollectionUtils.intersection(old, new);
Collection<T> newResult = (Collection<T>)CollectionUtils.subtract(new, old);
(You need the (unchecked) casts because CollectionUtils isn't generified.)
I would use Apache CollectionUtils and use the union (items in both) and disjunction functions (change the order to get one or the other).
Ideally you'd make one pass over all the elements instead of 3, but if this isn't your bottleneck, I wouldn't worry about efficiency right now.
Personally, I believe that the only sensible way to explain the difference between two lists is with a full-blown diff algorithm (like that of the unix diff command).
Sets, though, are a much simpler story. Google Collections provides a Sets.difference(Set, Set) method, as well as union and intersection.
I think you can accomplish this with the standard java library too. Take a look at the following methods of java.util.Collection:
retainAll(Collection c)
Retains only the elements in this collection that are contained in the specified collection (optional operation). In other words, removes from this collection all of its elements that are not contained in the specified collection.
removeAll(Collection c)
Removes all this collection's elements that are also contained in the specified collection (optional operation). After this call returns, this collection will contain no elements in common with the specified collection.
If there is a standard way, I don't know it...
I looked at Collections but only saw disjoint() (that's already an information...) and indexOfSubList() (not sure if it is useful at all).
I also looked at Google Collections and if there is, apparently, not such facility, there are some useful tools there, like Collections2's filter() function which can help if you make a proper Predicate.
[EDIT] I missed the removeAll and retainAll methods of Collection... I don't delete this answer, even if a bit pathetic, as it is somehow complementary of the other answers... (I think Google Collections is at least worth mentioning!)
精彩评论