Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map value at index 0 for a list in an Optional Stream

Tags:

java

java-8

I have the following method which is working fine. I am trying to accomplish everything and get the value inside that Optional stream without having to do the additional if check. Is it possible to map and get the Result object at index 0? Please advice thanks.

public String getData(HttpEntity<Request> request, String endPoint){
    ResponseEntity<Reponse> response = 
        template.exchange(endPoint, HttpMethod.POST, request, Reponse.class);

    List<Result> results = Optional.ofNullable(response)
        .map(ResponseEntity::getBody)
        .map(Response::getQueryResult)
        .map(QueryResult::getResults)
        // getResults is an ArrayList of Result Objects. Could I get the Result Object at index 0 here? 
        // following that I plan to go .map(Result::getValue) here. 
        .orElse(null);
    if(CollectionUtils.isNotEmpty(results)){
        return results.get(0).getValue();
    }
    return null;
}
like image 538
karvai Avatar asked Apr 06 '20 14:04

karvai


People also ask

What does optional map return?

Like Stream, Optional#map will return a value wrapped by a Optional.


3 Answers

return Optional.ofNullable(response)
               .map(ResponseEntity::getBody)
               .map(Response::getQueryResult)
               .map(QueryResult::getResults)
               .filter(CollectionUtils::isNotEmpty)
               .map(list -> list.get(0)) // hate this part :)
               .map(Result::getValue)
               .orElse(null);

If you are a fan of method references, and you find lambdas boring

return Optional.ofNullable(response)
               .map(ResponseEntity::getBody)
               .map(Response::getQueryResult)
               .map(QueryResult::getResults)
               .filter(CollectionUtils::isNotEmpty)
               .map(List::iterator)
               .map(Iterator::next)
               .map(Result::getValue)
               .orElse(null);

I showed it for educational reasons, I don't advocate it even though I like it.

like image 174
Andrew Tobilko Avatar answered Oct 14 '22 23:10

Andrew Tobilko


Assuming that the ArrayList is never null:

.flatMap(r -> r.stream().findFirst())

This takes the list, streams it, gets an Optional with the first element (or an empty Optional if the list is empty. Lastly, since an Optional<Optional<Result>> isn't that useful, we use flatMap instead of map to collapse it into an Optional<Result>.

like image 38
BambooleanLogic Avatar answered Oct 15 '22 00:10

BambooleanLogic


change that orElse to return an empty List and stream from there. In such a way you can invoke findFirst safely - as for an empty List it will return Optional::empty and from there - you either map it (in case you do have it) to Result::getValue or, in case such a List is not present - null, so it is exactly as your program flow.

...
   .map(QueryResult::getResults)
   .orElse(Collections.emptyList())
   .stream()
   .findFirst()
   .map(Result::getValue)
   .orElse(null);
like image 37
Eugene Avatar answered Oct 14 '22 23:10

Eugene