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

を失いたくない場合は、おそらくこのコードが役立ちます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.Objectcontains(Object)ob1.equals(obj2)

メソッド内のロジックは、メソッドの条件equals()に記述されているものと似ている必要がありますhasMyClassif

于 2013-04-08T17:37:45.673 に答える
0

NewList の項目を HashSet に入れます。(NewList でオブジェクトをインスタンス化する方法に応じて、HashSet でカスタム IEqualityComparer を使用する必要がある場合があります。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 に答える