3

我需要以以下方式使用新的 List 集合更新 List 集合:

  • 原始列表从新列表中获取新项目
  • 原始列表中不在新列表中的项目将被删除

不幸的是,清除原始列表并从新列表重建它不是一种选择,因为那些已经包含具有重要值/引用的对象,我不想丢失。

我需要实现的可以总结如下:

在此处输入图像描述

我想出了“某种”可行的“某种”解决方案,但我真的不喜欢它,而且我不确定它的效率如何......

class MyClass{
int someInt;
String someString;
int rowID; // DB reference, cannot lose it...
... 
}

public static List<MyClass> mergeMyClassLists(List<MyClass> origList, List<MyClass> newList){

    Integer index[]= new Integer[origList.size()];

    // Find the ones to remove from the old list
    int c=0;
    for(MyClass origMyClass:origList){       
       if(!hasMyClass(newList,origMyClass)) index[c] = origList.indexOf(origMyClass);
    c++;  
    }    

    // Then remove them
    for(int i:index){
    if(index[i]!=null)
        origList.remove(index[i]);
    }

    //Add new ones
    for(MyClass newMyClass:newList){        
        if(!hasMyClass(origList,newMyClass)) origList.add(newMyClass);      
    }           
return origList;
}

private static boolean hasMyClass(List<MyClass> myClassList, MyClass myClass){

    for(MyClass mc:myClassList){
        // Are they the same? based on my own criteria here
        if(mc.someInt == myClass.someInt && mc.someString.equals(myClass.someString)) return true; 
    }
    return false;
}

有没有更好/标准的方法来做到这一点?我觉得我可能使情况过于复杂...

4

4 回答 4

1

覆盖equals并满足您对平等的要求hashCodeMyClass

这是一个例子:

public boolean equals(Object o) {
    if( !(o instanceof MyClass) ) return false;

    MyClass mc = (MyClass)o;
    if(this.someInt != mc.someInt)
        return false;
    return (this.someString == null)
            ? mc.someString == null
            : this.someString.equals(mc.someString);
}
public int hashCode() {
    int hashCode = someInt;
    if(someString != null)
        hashCode ^= someString.hashCode();
    return hashCode;
}

当你覆盖了这些,它就像这样简单:

origList.retainAll(newList);
newList.removeAll(origList);
origList.addAll(newList);
于 2013-04-08T18:02:49.640 回答
0

按照你的要求,我想对你来说最重要的只是newList. 所以,间接地你想删除所有元素originalList并将所有元素添加newListoriginalList. 因此,我认为您应该简单地写下,而不是做所有这些事情:

originalList = new ArrayList<MyClass>(newList);
于 2013-04-08T17:15:03.903 回答
0

如果您不想丢失,那么originalList此代码可能会有所帮助

List<String> orgList = new ArrayList<String>();
orgList.add("a");
orgList.add("b");

List<String> newList  = new ArrayList<String>();
newList.add("a");
newList.add("d");
newList.add("e");
newList.add("f");

List<String> result = new ArrayList<String>();
List<String> existingInBoth = new ArrayList<String>();
//Add item to result, if its present in newList BUT not in orgList
for(String s : newList) {
    if(!orgList.contains(s))
    result.add(s);
}
//Add the common items (this is inverse of removing the item which is there in orgList and not in newList)
for(String s : orgList) {
    if(newList.contains(s))
    existingInBoth.add(s);
}
result.addAll(existingInBoth);
System.out.println(result);

为此,您需要创建类的MyClass覆盖equals()方法java.lang.Object并定义对象的相等性。原因是,该contains(Object)方法本质上是通过检查对象与集合中所有元素的相等性( )来检查集合中对象的存在。ob1.equals(obj2)

方法内部的逻辑equals()应该和hasMyClass方法if条件中写的逻辑类似

于 2013-04-08T17:37:45.673 回答
0

将 NewList 中的项目放在 HashSet 中。(您可能需要在 HashSet 中使用自定义 IEqualityComparer,具体取决于您在 NewList 中实例化对象的方式 - 给定 OldList 中的 Object1 和 NewList 中的 Object2,如果 Object1 == Object2,您可以使用 HashSet 的默认构造函数,但是您如果 Object1 != Object2 和 Object1.equals(Object2),则需要创建自定义 IEqualityComparer。)遍历 OldList - 如果 NewHashSet.contains(object) 则从 NewHashSet 中删除对象,否则从 OldList 中删除对象。接下来,遍历 NewHashSet,并将剩余的对象添加到 OldList。HashSet.contains 在或多或少的恒定时间内运行,因此整个合并方法将以线性时间运行。

于 2013-04-08T17:42:29.680 回答