我已经创建了一个我认为您正在寻找的近似值,只是使用 Java 中的 Collections Framework。坦率地说,我认为正如@Mike Deck 指出的那样,这可能是矫枉过正。对于这样一小部分要比较和处理的项目,我认为从程序的角度来看,数组会是一个更好的选择,但这是我的伪编码(因为我很懒)解决方案。我假设 Foo 类基于它的唯一 id 而不是其内容中的所有数据是可比较的:
Collection<Foo> oldSet = ...;
Collection<Foo> newSet = ...;
private Collection difference(Collection a, Collection b) {
Collection result = a.clone();
result.removeAll(b)
return result;
}
private Collection intersection(Collection a, Collection b) {
Collection result = a.clone();
result.retainAll(b)
return result;
}
public doWork() {
// if foo is in(*) oldSet but not newSet, call doRemove(foo)
Collection removed = difference(oldSet, newSet);
if (!removed.isEmpty()) {
loop removed {
Foo foo = removedIter.next();
doRemove(foo);
}
}
//else if foo is not in oldSet but in newSet, call doAdd(foo)
Collection added = difference(newSet, oldSet);
if (!added.isEmpty()) {
loop added {
Foo foo = addedIter.next();
doAdd(foo);
}
}
// else if foo is in both collections but modified, call doUpdate(oldFoo, newFoo)
Collection matched = intersection(oldSet, newSet);
Comparator comp = new Comparator() {
int compare(Object o1, Object o2) {
Foo f1, f2;
if (o1 instanceof Foo) f1 = (Foo)o1;
if (o2 instanceof Foo) f2 = (Foo)o2;
return f1.activated == f2.activated ? f1.startdate.compareTo(f2.startdate) == 0 ? ... : f1.startdate.compareTo(f2.startdate) : f1.activated ? 1 : 0;
}
boolean equals(Object o) {
// equal to this Comparator..not used
}
}
loop matched {
Foo foo = matchedIter.next();
Foo oldFoo = oldSet.get(foo);
Foo newFoo = newSet.get(foo);
if (comp.compareTo(oldFoo, newFoo ) != 0) {
doUpdate(oldFoo, newFoo);
} else {
//else if !foo.activated && foo.startDate >= now, call doStart(foo)
if (!foo.activated && foo.startDate >= now) doStart(foo);
// else if foo.activated && foo.endDate <= now, call doEnd(foo)
if (foo.activated && foo.endDate <= now) doEnd(foo);
}
}
}
至于您的问题:如果我将 oldSet 和 newSet 转换为 HashMap (这里不关心顺序),以 ID 作为键,它是否会使代码更易于阅读和比较?转换会损失多少时间和内存性能?我认为您可能会通过使用 Map BUT 使代码更具可读性......您可能会在转换过程中使用更多的内存和时间。
迭代这两组并执行适当的操作会更有效和简洁吗?是的,这将是两全其美的方法,特别是如果您遵循@Mike Sharek 的建议,即使用专门的方法滚动您自己的列表,或者遵循类似访客设计模式的方法来运行您的收藏并处理每个项目。