Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to filter elements that throw exception during stream map

I was following the article https://www.oreilly.com/ideas/handling-checked-exceptions-in-java-streams for extracting a method into a method, in order to handle exceptions, and noticed the examples given only look clean since they don't actually compile because they miss a return statement.
Essentially I'm looking to have a parse method similar to this "divide" in the article example 3, but mine parses the list and in some scenarios it will throw errors log them and continue, like this:

public List<String> validator(List<String> values) {
    return values.stream()
        .map(this::parse)
        .filter(Objects::nonNull)
        .collect(Collectors.toList());
}
public String parse(String s){
    try{
         // returns something or throws exceptions
    } catch (Exception e ){
       log(e)
    }
    return null;
}

As you can see from this code I cheated the compilation error by returning a null at the end of the parse method that I then filter nulls on my validator before collecting, and it looks appalling. Is there a better way to skip the values in a clean easy way?

like image 277
user7673492 Avatar asked Oct 23 '25 04:10

user7673492


1 Answers

As for me your way of skipping null elements is pretty good.

However if you want to do it in functional way, then avoid returning null at all. Return an Optional instead:

public Optional<String> parse(String s){
    try{
        return Optional.of(<parsed_value>);
    } catch (Exception e ){
        log(e);
    }
    return Optional.empty();
}

Java 1.8 solution:

public List<String> validator(List<String> values) {
     return values.stream()
                  .map(this::parse)
                  .filter(Optional::isPresent)
                  .map(Optional::get)
                  .collect(Collectors.toList());
}

Java 1.9+ solution: (as proposed by @Holger already):

 public List<String> validator(List<String> values) {
     return values.stream()
                  .map(this::parse)
                  .flatMap(Optional::stream)
                  .collect(Collectors.toList());
}
like image 133
ETO Avatar answered Oct 24 '25 20:10

ETO