I have two HashSets with same type of objects. My search criteria is like, search in first set and if not present then search in another set. I had tried with Stream layer with following steps as given below
Set<MyObject> firstSet = new HashSet<>();
Set<MyObject> secondSet = new HashSet<>();
and these two sets are having some values.
Predicate<MyObject> match = myObject -> StringUtils.equals(myValue, myObject.getMyValue());
firstSet.values().stream().filter(match).findFirst()
.orElse(secondSet.values().stream().filter(match)
.findFirst().orElseThrow(()-> new MyException()));
My matching object is in First Set and i have tried to get it by manually and i got it... but using the above iteration, i always get the exception even when the first set has the matched object. Kindly correct me.. thanks is advance.
Your problem is that you are not using Optional.orElse
as expected.
When you use Optional.orElse
, its parameter is evaluated eagerly. This means that your second set is being searched first, to resolve the parameter of your first set's Optional.orElse
.
Instead, use Optional.orElseGet
, which receives a Supplier
that is evaluated lazily:
firstSet.stream()
.filter(match)
.findFirst()
.orElseGet(() -> secondSet.stream()
.filter(match)
.findFirst()
.orElseThrow(()-> new MyException()));
EDIT: As suggested by Holger in the comments, there is an easier way:
Stream.of(firstSet, secondSet)
.flatMap(Set::stream)
.filter(match)
.findFirst()
.orElseThrow(MyException::new);
Streaming the sets first and then calling flatMap
ensures that elements of the first set will all appear before elements of the second set.