2013-04-08 3 views
3

Мне нужно обновить коллекцию List с новой коллекцией списка таким образом, что:Обновление коллекции Список <MyClass> на основе нового списка <MyClass> коллекция

  • оригинальный список получает новые предметы из нового списка
  • элементы в первоначальном списке, которые не находятся на новом списке удаляются

к сожалению, очистка исходного списка и восстановления его из новой не вариант, потому что те уже имеют объекты с важными ценностями/ре я не хочу терять.

Что мне нужно, чтобы достичь можно резюмировать следующим образом:

enter image description here

я придумал «какой-то» решение, которое «рода» работает, но я действительно не нравится, и я не уверен, насколько эффективно это ...

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; 
} 

есть ли лучше/стандартный способ сделать это? У меня такое чувство, что я могу быть слишком усложняющим ситуацию ...

+0

Как насчет использования карты? – BobTheBuilder

+3

'origList.retainAll (newList); newList.removeAll (origList); origList.addAll (newList); 'может быть? Нужен хороший 'MyClass.equals, hashcode'. –

+0

Я хочу совместить объекты, которые могут быть не совсем одинаковыми (например, у одного из них нет значения для rowID), но они совпадают в зависимости от установленного мною условия. – Crocodile

ответ

1

Переопределить equals и hashCode в MyClass в соответствии с вашими требованиями в отношении равенства.

Вот пример:

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); 
+0

Это работает, но для чего hashCode()? По-моему, никогда не получается, когда я отлаживаю свой код. – Crocodile

+0

@Croc Некоторые коллекции сравнивают хеш-коды при проверке равенства, потому что сравнение 'int' быстрее, чем вызов 'equals'. Например, «HashSet's» и «HashMap» сравнивают хеш-коды при проверке равенства. По этой причине 'hashCode' всегда должен быть переопределен всякий раз, когда вы переопределяете' equals'. Равные объекты должны иметь один и тот же хэш-код, но для неравных объектов необязательно иметь разные хеш-коды, хотя это предпочтительнее для более высокой производительности. –

0

Выполнение ваших требований Я думаю, что для вас самое главное - это только элементы newList. Таким образом, косвенно вы хотите удалить все элементы originalList и добавить все элементы newList в originalList. Таким образом, вместо того, чтобы делать все эти вещи, я думаю, вы должны просто написать:

originalList = new ArrayList<MyClass>(newList); 
+0

Если я удалю все объекты из исходного списка, я получу некоторые из их значений полей. (например: rowID) Объекты в новом списке могут не совпадать, но они сопоставляются на основе простого условия. Это всегда объект в исходном списке, который мне нужно сохранить, если они совпадают. – Crocodile

+0

См., Что я вижу после прочтения вашего вопроса и таблицы истинности, которые вы опубликовали, является то, что если записи 'originalList' совпадают с' newList', а затем 'Keep it' в' originalList', просто удалите его. И добавьте все новые элементы из 'newList' в' originalList'. Вот что я здесь делаю. Или, возможно, вам нужно больше убрать свой вопрос. –

+0

Спасибо, что посмотрели на это. Ваш последний комментарий правильный, но он противоречит вашему ответу ... если я поеду с фрагментом кода в вашем ответе, я потеряю все объекты из исходного списка. Если я что-то не хватает ... – Crocodile

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 условия

0

помещаете элементы в NewList в HashSet. (Возможно, вам понадобится использовать пользовательский IEqualityComparer в HashSet в зависимости от того, как вы создаете объекты в NewList - данный Object1 из OldList и Object2 из NewList, вы можете использовать конструктор по умолчанию для HashSet, если Object1 == Object2, Вам нужно создать пользовательский IEqualityComparer, если Object1! = Object2 и Object1.equals (Object2).) Итерация, хотя OldList - если NewHashSet.contains (объект), то удалить объект из NewHashSet, в противном случае удалить объект из OldList. Затем выполните итерацию через NewHashSet и добавьте оставшиеся объекты в OldList. HashSet.contains работает в более или менее постоянном времени, поэтому весь метод слияния будет выполняться в линейном времени.

Смежные вопросы