Как использовать методы Collections (removeAll () и retainAll ()) для двух объектов - PullRequest
0 голосов
/ 16 декабря 2010

Я ожидал результата ниже, но на самом деле нет. Хотя это работало, когда я пытался использовать String вместо Item Object. Я хотел бы знать, почему причины этого и как кодировать, чтобы получить ожидаемый результат. Спасибо.

EXPECTED
------------------------------
removed object are:
2
same object are:
1
3
add object are:
4
------------------------------

ACTUAL
------------------------------
removed object are:
1
2
3
same object are:
add object are:
1
3
4
------------------------------

package com.javastudy;

import java.util.ArrayList;
import java.util.List;

public class CollectionCompareToObjects {

 public static void main(String[] args) {

  List<Item> before = new ArrayList<Item>();
  List<Item> after = new ArrayList<Item>();

  before.add(new Item(1L));
  before.add(new Item(2L)); // delete
  before.add(new Item(3L));

  after.add(new Item(1L));
  after.add(new Item(3L));
  after.add(new Item(4L)); // added

  List<Item> removed = new ArrayList<Item>(before);
  removed.removeAll(after);

  System.out.println("removed objects are:");
  for(Item item : removed){
   System.out.println(item.getId());
  }

  List<Item> same = new ArrayList<Item>(before);
  same.retainAll(after);

  System.out.println("same objects are:");
  for(Item item : same){
   System.out.println(item.getId());
  }

  List<Item> added = new ArrayList<Item>(after);
  added.removeAll(before);

  System.out.println("add objects are:");
  for(Item item : added){
   System.out.println(item.getId());
  }

 }

}

package com.javastudy;

public class Item {

 Long id;

 public Item(Long id) {
  this.id = id;
 }

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

}

Ответы [ 5 ]

5 голосов
/ 16 декабря 2010

Вы не реализовали функцию equals (), поэтому ВСЕ ваши Предметы - это разные объекты, некоторые из которых имеют одинаковое поле.

Вы должны реализовать равно.

Я также предлагаю вам использовать long вместо Long, если вы не хотите id = null.

2 голосов
/ 16 декабря 2010

внедрите equals() и hashCode() в свой класс предметов, например как это:

@Override
public int hashCode(){
    return Objects.hash(id);
}

@Override
public boolean equals(Object obj){
    if(this == obj) return true;
    else if(obj instanceOf Item){ // implicit null check
        Item other = (Item) obj;
        return Objects.equals(this.id, other.id);
    }
    else return false;
}

Полагаю, после этого все будет работать как положено.

2 голосов
/ 16 декабря 2010

Вы должны переопределить метод equals(..) вашего Item и сравнить поле id (в основном, метод equals должен просто сделать return id.equals(other.getId()) с соответствующими нулевыми проверками.

С equalsприходит и hashCode() - оба метода всегда должны быть реализованы вместе, с одинаковыми полями.

И вам необходимо переопределить эти методы, потому что методы removeAll и retainAll работают путем итерации коллекций исравнение существующих предметов с предметами из переданной коллекции через equals(..)

0 голосов
/ 16 декабря 2010

Когда вы дважды создаете экземпляр Item даже с одним и тем же параметром, у вас будет 2 разных объекта. Два решения:

  • использовать ту же ссылку
  • переопределить равно от объекта
0 голосов
/ 16 декабря 2010

Вам необходимо переопределить методы equals и hashCode вашего класса Item. Если нет, то Java использует реализацию по умолчанию equals, что эквивалентно ==:

Item first = new Item(1);
Item second = new Item(1);
System.out.println(first == second); // Prints false, as expected: they are different objects.
System.out.println(first.equals(second)); // Prints false because of the default equals method.

Если вы правильно реализуете equals, то результатом будет false, за которым следует true.

...