Jithin M V
Jithin M V

Reputation: 393

Why Java streams are not able to handle exception even after surrounding with a try-catch block?

I have the following piece of code with Java streams

Problematic code

You can see that I am having an error on the 4th line. Basically the error says "Unhandled Exception: AddressException". But you can see that I am catching it within a catch block. But still that is not working. Even though, if I use a try catch block within the map method it works as shown below:

public List<InternetAddress> getListOfInternetEmailAddresses(List<String> toEmails){
     List<InternetAddress> internetAddresses = new ArrayList<>();
          internetAddresses = toEmails.stream().map(a->{
              InternetAddress ia = null;
              try{
                 ia = new InternetAddress(a);
              } catch (AddressException e) {
                  
              }
              return ia;
          }).collect(Collectors.toList());
      return internetAddresses;
}

Does anyone know why this behaviour and if knows please give some insights to that. One more quetion, will the anonymous inner class also behave the same?

Upvotes: 0

Views: 657

Answers (1)

AleksanderSzporka
AleksanderSzporka

Reputation: 136

Error is shown because you provided method with different signature (additional thows clause). You have to provide implementation that is compatible with java.util.function.Function#apply signature

R apply(T var1);

There is several ways to deal with your problem:

  • anonymous function with try-catch
    public List<InternetAddress> getListOfInternetEmailAddresses(List<String> toEmails) {
        return toEmails.stream().map(new Function<String, InternetAddress>() {
            @Override
            public InternetAddress apply(String email) {
                try {
                    return new InternetAddress(email);
                } catch (AddressException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }).collect(Collectors.toList());
    }
  • try-catch in lambda
    public List<InternetAddress> getListOfInternetEmailAddresses(List<String> toEmails) {
        return toEmails.stream().map(email -> {
            try {
                return new InternetAddress(email);
            } catch (AddressException e) {
                e.printStackTrace();
            }
            return null;
        }).collect(Collectors.toList());
    }
  • extracted handling method
    public List<InternetAddress> getListOfInternetEmailAddresses(List<String> toEmails) {
        return toEmails.stream().map(this::createInternetAddress).collect(Collectors.toList());
    }

    private InternetAddress createInternetAddress(String email) {
        try {
            return  new InternetAddress(email);
        } catch (AddressException e) {
            e.printStackTrace();
        }
        return null;
    }
  • generalized extracted handling method
@FunctionalInterface
public interface FunctionThrowing <T, R, E extends Exception> {
    R apply(T var1) throws E;

    static <T, R, E extends Exception> Function<T, R> handled(FunctionThrowing<T, R, E> ft) {
        return result -> {
            try {
                return ft.apply(result);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }
}
    public List<InternetAddress> getListOfInternetEmailAddresses(List<String> toEmails) {
        List<InternetAddress> internetAddresses = new ArrayList<>();
        internetAddresses = toEmails.stream().map(FunctionThrowing.handled(InternetAddress::new)).collect(Collectors.toList());
        return internetAddresses;
    }

Upvotes: 4

Related Questions