Search code examples
java-streamiterationjava-9

Iteration of two identical Set using Java Streams


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.


Solution

  • 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.