I have a set of objects and trying to find if an object exist in list by id
. I do not want to override equals()
and hashCode()
.
class ABC {
Long id;
String name;
}
I want to do the below statement without overriding equals()
and hashCode()
methods
Set<ABC> abcSetOne;
Set<ABC> abcSetTwo;
abcSetOne.stream()
.filter(abcSetTwo::contains)
.collect(Collectors.toSet());
id
s are guaranteed unique.
I am using Java 8.
CodePudding user response:
Update
When need set intersection (in terms of set theory) of your object based on one attribute only without changing the existing hashCode()
and equals()
methods, you can create a HashSet
of id
s.
public static void main(String[] args) {
Set<ABC> abcSetOne = Set.of(new ABC(1L, "first"), new ABC(2L, "second"), new ABC(3L, "third"));
Set<ABC> abcSetTwo = Set.of(new ABC(1L, "first"), new ABC(5L, "fifth"), new ABC(3L, "third"));
Set<Long> idsOne = abcSetTwo.stream()
.map(ABC::getId)
.collect(Collectors.toSet());
Set<ABC> result = abcSetOne.stream()
.filter(abc -> idsOne.contains(abc.getId()))
.collect(Collectors.toSet());
System.out.println(result);
}
Output
[ABC{id=1, name='first'}, ABC{id=3, name='third'}]
When you need to establish uniqueness based on more than one object's property, you can define a wrapper class with the hashCode/equals
contract implemented based on these properties.
As a wrapper you can utilize of Java 16 record, that will make the code leaner (hashCode()
and equals()
will be generated by the compiler)
public record ABCWrapper(Long id, String name) {
ABCWrapper(Wrapping.ABC abc) {
this(abc.getId(), abc.getName());
}
}
For earlier versions, ABCWrapper
can be defined as a plain class.
main()
- demo
public static void main(String[] args) {
Set<ABC> abcSetOne = Set.of(new ABC(1L, "first"), new ABC(2L, "second"), new ABC(3L, "third"));
Set<ABC> abcSetTwo = Set.of(new ABC(1L, "first"), new ABC(5L, "fifth"), new ABC(3L, "third"));
Map<ABCWrapper, ABC> abcByWrapper = abcSetTwo.stream()
.collect(Collectors.toMap(ABCWrapper::new, Function.identity()));
Set<ABC> result = abcSetOne.stream()
.map(ABCWrapper::new)
.filter(abcByWrapper::containsKey)
.map(abcByWrapper::get)
.collect(Collectors.toSet());
System.out.println(result);
}
Output
[ABC{id=1, name='first'}, ABC{id=3, name='third'}]