Java Lambda for break inside two for loops

2020-03-31 java collections java-8 functional-programming java-stream

I am trying to convert an iterative block of code in Java 8 to functional. The functional approach is unable to find the matching message in the set shared.

List<Optional<Message>> allMessages = new ArrayList<>();

Set<Status> allStatuses = getAllStatuses();

//Iterative : Working
Set<StatusMessage> set = new HashSet<>(STATUS_MESSAGE.values());
for (StatusMessage statusMessage : set) {
    for (Status status : statusMessage.getStatusAndInfo().keySet()) {
        Optional<Message> message = MessageBuilder.createMessage(allStatuses, status, this::createMessage);
        if (message.isPresent()) {

//Functional : Not working  - Never adds anything to the 
//map even when matching status is present
        .map(statusMessage -> statusMessage.getStatusAndInfo().keySet())
        .map(key -> MessageBuilder.createMessage(allStatuses, key, this::createMessage))

The MessageBuilder.createMessage looks like this:

Optional<Status> matchingStatus =
System.out.println("Found : " + matchingStatus.toString());
return matchingStatus.flatMap(creator);

Also, for debugging purposes, how can I see what is happening at each step of the stream? The stack in the debugger in intellij wasn't showing anything in the stream.


This should do it:

        .forEach(statusMessage ->
                    .map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))


To build the result list using toList instead of adding to a list:

List<Optional<Message>> allMessages = STATUS_MESSAGE.values().stream()
        .flatMap(statusMessage ->
                    .map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))

This should be a comment, but it's too long...

Seems like your MessageBuilder.createMessage method is overcomplicated.

Check below a simplified and more readable version of the same logic:

if (allStatuses.contains(status)) {
    System.out.println("Found : " + status.toString());
    return creator.apply(status);
return Optional.empty();

You should not use forEach for accumulating operations, so this should be more idiomatic:

Function<StatusInfo, Optional<Message>> messageForStatus = statusInfo -> 
                    .map(status -> MessageBuilder.createMessage(allStatuses, status, this::createMessage))

allMessages = STATUS_MESSAGE.values().stream()

As a side note, you have too many optionals, you may want to consider unwrapping some earlier, as a list of optionals may just as well be the list of only the present values.