开发者

How to use Collections methods(removeAll() and retainAll()) for two objects

I expected to result below but actually not. Even though it worked when I tried to use String instead of Item Object. I would like to know why the reasons about that and how to code in order to get expected result.Thanks.

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.开发者_StackOverflow中文版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;
 }

}


You haven't implemented equals() so ALL your Items are different objects some happen to have a field which is the same.

You need to implement equals.

I also suggest you use long instead of Long, unless you want id = null.


You have to override the equals(..) method of your Item and compare the id field (basically, the equals method should simply do return id.equals(other.getId()), with the appropriate null-checks.

With equals comes and hashCode() - the two methods must always be implemented together, with the same fields.

And you need to override these methods, because the removeAll and retainAll methods work by iterating the collections and comparing the existing items with the items from the passed collection via equals(..)


implement equals() and hashCode() in your item class, e.g. like this:

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

I'm guessing it will work as expected after that.


You need to override the equals and hashCode methods of your Item class. If you don't then Java uses a default implementation of equals which is equivalent to ==:

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.

If you implement equals correctly then the output will be false followed by true.


When you instantiate twice an Item even with the same parameter, you will have 2 differents objects. Two solutions :

  • use the same reference
  • override equals from Object
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜