5

I am in the process of trying to better understand how to use Java streams. I have these classes:

public class Plan {

    List<Request> requestList;
}

public class Request {

    List<Identity> identityList;
    boolean isCancelled;

}

public class Identity {

    String idNumber;
}

I am trying to write a method that returns the plan that contains the non-cancelled request with a matching identity number.

This is what I have tried:

public static Plan findMatchingPlan(List<Plan> plans, String id) {
    List<Plan> filteredPlan = plans.stream()
            .filter(plan -> plan.getRequestList().stream()
                    .filter(request -> !request.isCancelled())
                    .filter(request -> request.getIdentityList().stream()
                        .filter(identity -> identity.getIdNumber().equals(id))))
            .collect(Collectors.toList());
}

This gives me an error:

java.util.stream.Stream<com.sandbox.Identity> cannot be converted to boolean

I sort of understand why there is an error. The nested filter returns a filter that cannot be evaluated as a boolean. The problem is, I don't know what I am missing.

Any help would be appreciated.

2
  • Make up your mind. Do you want a Plan (return type)( or a List<Plan> *(local variable). If just a single Plan, do you want first, any, or last match? Commented Apr 26, 2018 at 23:05
  • @Andreas first match of plan is ideal. My apologies for not cleaning this up. Commented Apr 26, 2018 at 23:13

1 Answer 1

6

Assuming you want first matching Plan, it can be done like this, using lambda expressions:

public static Plan findMatchingPlan(List<Plan> plans, String id) {
    return plans.stream()
                .filter(plan -> plan.getRequestList()
                                    .stream()
                                    .filter(request -> ! request.isCancelled())
                                    .flatMap(request -> request.getIdentityList().stream())
                                    .anyMatch(identity -> identity.getIdNumber().equals(id)))
                .findFirst()
                .orElse(null);
}

Or like this, using method references, and finding any matching Plan:

public static Plan findMatchingPlan(List<Plan> plans, String id) {
    return plans.stream()
                .filter(plan -> plan.getRequestList()
                                    .stream()
                                    .filter(request -> ! request.isCancelled())
                                    .map(Request::getIdentityList)
                                    .flatMap(List::stream)
                                    .map(Identity::getIdNumber)
                                    .anyMatch(id::equals))
                .findAny()
                .orElse(null);
}
Sign up to request clarification or add additional context in comments.

3 Comments

ah, thank you. so was my issue that I was just filtering without specifying what to do with the filtered streams?
Would be nice to have the method return Optional<Plan> to avoid dealing with nullity as well as improving code documentation.
@Seephor No, your problem was that filter() is not a terminal operation. In my solution, anyMatch and findAny are both terminal operations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.