Replacing isPresent with ifPresent and orElse

Viewed 684

I have the following logic in my method where I check for the value of an optional parameter, and depending on that I build another object.

AtomicReference<Employee> employeeValue = null;
    questions.forEach(question -> {
        if(question.isBoolean().isPresent()) {
            employeeValue.set(Employee.builder()
                    .withBooleanValue(Boolean.valueOf(question.value()))
                    .build());
        } else {
            employeeValue.set(Employee.builder()
                    .withStringValue(question.value())
                    .build());
        }
        Record record = Record.builder()
                .withId(question.id())
                .withValue(employeeValue.get())
                .build();
        answers.add(record);
    });

How can I replace the above with ifPresent and orElse? I'm using Java 8 and therefore ifPresentOrElse method is not available. If I am to use ifPresent and orElse separately with anonymous inner function, how do I go about it?

Any help would be much appreciated.

2 Answers

You neither need isPresent() nor ifPresent(). You don’t need peek() (as in the other answer) nor an AtomicReference (as in the question). I believe that this does it:

    questions.forEach(question -> {
        Employee empl = question.isBoolean()
                .map(b -> Employee.builder()
                        .withBooleanValue(Boolean.valueOf(question.value()))
                        .build())
                .orElseGet(() -> Employee.builder()
                        .withStringValue(question.value())
                        .build());
        Record record = Record.builder()
                .withId(question.id())
                .withValue(empl)
                .build();
        answers.add(record);
    });

You can probably apply this idea inside the stream from the other answer if you want. Rather than using Stream.forEach() I’d prefer to collect into a collection like a list and then use answers.addAll().

You can stream through questions and use peek and map-orElse construction to achieve the same result:

questions.stream()
    .peek(question -> {
            Employee employee = question.isBoolean()
                .map(b -> Employee.builder().withBooleanValue(Boolean.valueOf(question.value())).build())
                .orElse(Employee.builder().withStringValue(question.value()).build());
            employeeValue.set(employee);
        }
    )
    .map(question -> Record.builder().withId(question.id()).withValue(employeeValue.get()).build())
    .forEach(answers.add(answer)); // did you mean 'record'?
    

But to be honest it does not change a lot - your implementation looks maybe less "java eightish" but is fine :)

Related