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
精彩评论