Java 比较两个列表的算法
我有一个在屏幕上显示的对象列表。用户可以随意更改,然后点击提交。在submit方法中,我获取存储的原始列表和当前列表,并对它们进行比较。我必须创建第三个列表,其中包含使用操作代码添加、删除或更改的所有对象,以指定要添加的对象。对象具有标识它们的id,默认为0 我该怎么做?这是我能想到的最好的(伪代码),但它看起来很马虎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
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;
}