比较两个列表的算法

时间:2013-06-19 19:01:42

标签: java algorithm list data-structures

我有一个我在屏幕上显示的对象列表。用户可以根据需要更改它们,然后点击提交。在提交方法中,我将获取我存储的原始列表和当前列表,并进行比较。我必须创建第三个列表,其中包含使用操作代码添加,删除或更改的所有对象,以指定它是什么。对象具有标识它们的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

2 个答案:

答案 0 :(得分:5)

如果排序无关紧要,您关心的是元素是否已添加或删除,您可能需要考虑更改数据结构并使用Set而不是ListSet类型专门用于确定元素是否存在并且有效地执行此操作,代价是您不再记住元素的顺序。

例如,使用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 ... */
    }
}

希望这有帮助!

答案 1 :(得分:2)

通过连续维护3向结果列表,您可以通过一个循环完成。如果您可以覆盖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);
        }
    }
}

请注意,我推测equals()会检查id,而compareTo()会检查所有其他字段。

<强>解释

您移除了deletedListnewList中同时存在的所有元素,因此结果是已删除项。

您将所有新元素添加到原始列表中不存在的addedList

如果两者都存在且对象不同,则会转到changedList

如果两者都存在且对象相同,那么我们不会将其添加到任何地方。

备注:

如果新对象的ID为0,则它们将不会出现在origList中(因为我们假设它们已经创建)。

当我上次实现这个时,我创建了一个单独的方法来逐个字段地比较对象,所以我可以将比较逻辑与标准Java方法分开(实际上它也是在interface

我使用List创建了这个,但实际上您可以将它与任何类型的Collection一起使用。与List一起使用将保留原始订单。

<强>更新

尝试以这种方式覆盖equals(我跳过了类型检查和转换):

public boolean equals(T other) {
    if (this.id == 0) {
        return this == other;
    }
    return this.id == other.id;
}

尚未创建的实例仅等于它们自己。已经创建的那些由id。

检查