Java 比较两个列表的算法

Java 比较两个列表的算法,java,algorithm,list,data-structures,Java,Algorithm,List,Data Structures,我有一个在屏幕上显示的对象列表。用户可以随意更改,然后点击提交。在submit方法中,我获取存储的原始列表和当前列表,并对它们进行比较。我必须创建第三个列表,其中包含使用操作代码添加、删除或更改的所有对象,以指定要添加的对象。对象具有标识它们的id,默认为0 我该怎么做?这是我能想到的最好的(伪代码),但它看起来很马虎 for (currentObject : objects in current list) if (currentObject.id is 0) //Wa

我有一个在屏幕上显示的对象列表。用户可以随意更改,然后点击提交。在submit方法中,我获取存储的原始列表和当前列表,并对它们进行比较。我必须创建第三个列表,其中包含使用操作代码添加、删除或更改的所有对象,以指定要添加的对象。对象具有标识它们的id,默认为0

我该怎么做?这是我能想到的最好的(伪代码),但它看起来很马虎

for (currentObject : objects in current list)
    if (currentObject.id is 0)
        //Was added
    for (oldObject : objects in original list)
        if (currentObject.id == oldObject.id)
            //Existed - compare other fields to see if changed

for (oldObject1 : objects in original list)
    boolean existed = false;
    for (currentObject1 : objects in current list)
        if(oldObject1.id == currentObject1.id)
            existed=true;
    if (!existed)
        //Was removed

如果排序不重要,你所关心的是元素是否被添加或删除,你可能需要考虑改变你的数据结构并使用<代码> SET<代码>而不是<代码>列表。

集合
类型专门用于确定元素是否存在并有效地执行此操作,但代价是您不再记得元素的顺序

例如,使用
HashSet
,可以执行以下操作:

Set<T> oldElems = new HashSet<T>(originalList);
Set<T> newElems = new HashSet<T>(currentList);

for (T obj : oldElems) {
    if (!newElems.contains(obj)) {
        /* ... this object was removed ... */
    }
}

for (T obj : newElems) {
    if (!oldElems.contains(obj)) {
        /* ... this object was added ... */
    }
}
Set oldElems=new HashSet(originalList);
Set newElems=newhashset(currentList);
对于(对象:旧元素){
如果(!newElems.contains(obj)){
/*…此对象已被删除*/
}
}
对于(目标:纽伦斯){
如果(!oldElems.contains(obj)){
/*…此对象已添加*/
}
}

希望这有帮助

通过持续维护三向结果列表,您可以通过一个循环完成。如果您可以重写
equals()
以依赖
id
s,那就好了。如果没有,请检查“更新”下的代码

以下是代码,请参见下面的说明:

List<T> origList = ...;
List<T> newList = ...;

List<T> addedList = new ArrayList<T>();
List<T> deletedList = new ArrayList<T>();
List<T> changedList = new ArrayList<T>();

deletedList.addAll(origList);

for(T t : newList) {
    int origIndex = deletedList.indexOf(t);
    if (origIndex < 0) {
        addedList.add(t);
    } else {
        T origT = deletedList.remove(origIndex);
        if(t.compareTo(origT) != 0) {
            changedList.add(t);
        }
    }
}

尚未创建的实例仅与其自身相等。已创建的对象将按id进行检查。

对象id是否唯一?如果对象id唯一,则在比较原始列表和当前列表之前,您可以通过对它们进行排序获得很多好处。@DavidH对象id从数据库中唯一。但是,添加到UI上的所有对象的id都是0。而且,如果我没记错的话,Java有一种方法来标识两个集合的公共元素。@Daniel-有一些操作像
retainal
removeAll
,但它们破坏性地修改了原始容器。虽然这可能是OP想要的?对于要在
HashSet
中使用的类型,您需要确保
equals()
hashCode()
正确实现。我发现您只处理添加和删除,那么修改后的案例呢?@CostiCiudatu-您可以将修改视为添加后再删除(反之亦然)。丹尼尔:我试着用“全部保留”和“全部删除”,但都不起作用。例如,如果我使用oldList和removeAll(newList)来获取所有删除的元素,它会将修改计算为删除,而事实并非如此。我遇到的覆盖问题是,在UI上,当它们单击“删除”时,我的操作侦听器正在调用list.remove(对象o)。通过像这样重写equals,它导致了一个bug,因为UI上列表中所有新添加的项的id都为0。因此,当我删除它时,它只是删除它找到的第一个id为0的对象,而不一定是他们选择删除的对象。顺便说一句,这是一个JSF应用程序。如果你不能使用
equals()
,那么你可以用
迭代器
循环替换
remove()
。我会更新我的答案。听起来不错,我会看看。看看你的代码,我想你指的是addedList.add(t)而不是newList.add(t)对吗?那部分让我有点不舒服。@B豪斯是的,我错了。现在更正并添加了
remove()
的代码。您提供的equals覆盖很好,可以解决我的另一个问题。回到您最初的建议,行T origT=deletedList.remove(T)这是一个语法错误,因为remove(Obj)返回一个布尔值。根据你想做的事情,我想我可以使用布尔值,将下一个if改为if(!booleanReturnedAbove),但是我对下一行的工作方式感到困惑。
public boolean equals(T other) {
    if (this.id == 0) {
        return this == other;
    }
    return this.id == other.id;
}