Reputation: 1948
I need to obtain a set difference between two sets/lists but the objects in these sets are constructed differently. I would like the set difference be calculated on only one field of these objects, how can I do this?
POJO o1 = new POJO();
o1.setName("Bean");
o1.setLocation("Boston");
POJO o2 = new POJO();
o2.setName("Bagel");
o2.setLocation("NYC");
POJO o3 = new POJO();
o3.setName("Bean");
List<POJO> p1 = new ArrayList<>();
p1.add(o1);
p1.add(o2);
List<POJO> p2 = new ArrayList<>();
p2.add(o3);
Collection<POJO> subList = CollectionUtils.subtract(p1, p2);
System.out.println("subList: "+subList.toString());
The output I see is : subList: [POJO(name=Bean)]
i.e. o3
. But for my use case, o1
and o3
are the same - how can I achieve this? I overrode the default equals()
method as well but i don't think it is invoked.
Upvotes: 3
Views: 1008
Reputation: 6686
You can use a UnifiedSetWithHashingStrategy
from Eclipse Collections:
POJO o1 = new POJO();
o1.setName("Bean");
o1.setLocation("Boston");
POJO o2 = new POJO();
o2.setName("Bagel");
o2.setLocation("NYC");
POJO o3 = new POJO();
o3.setName("Bean");
HashingStrategy<POJO> strategy = HashingStrategies.fromFunction(POJO::getName);
MutableSet<POJO> set1 =
HashingStrategySets.mutable.with(strategy, o1, o2);
MutableSet<POJO> set2 =
HashingStrategySets.mutable.with(strategy, o3);
MutableSet<POJO> difference = set1.difference(set2);
Assert.assertEquals("[POJO(name=Bagel)]", difference.toString());
This answer explains how UnifiedSetWithHashingStrategy
works in more detail.
Note: I am a committer for Eclipse Collections.
Upvotes: 4
Reputation: 37404
You can achieve this with the help of overloaded subtract with predicate.
Override hashcode
and equals
in POJO
class, (and toString for clean output)
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
POJO pojo = (POJO) o;
return Objects.equals(name, pojo.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
Use Predicate with set as
Collection<POJO> subList = CollectionUtils.subtract(p1, p2, new Predicate<POJO>() {
@Override
public boolean evaluate(POJO object) {
return p1.contains(object); // might need to make p1 final
}
});
Result:
subList: [ Bagel ]
Note: Apache common does not support anything like Java 8 BiPredicate
Upvotes: 4