1

I answered this question

This is the code:

import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

The method!

private String[] getHostAddresses() {
  Set<String> HostAddresses = new HashSet<>();
  try {
    for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) {
      if (!ni.isLoopback() && ni.isUp() && ni.getHardwareAddress() != null) {
        for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
          if (ia.getBroadcast() != null) {  //If limited to IPV4
            HostAddresses.add(ia.getAddress().getHostAddress());
          }
        }
      }
    }
  } catch (SocketException e) { }
  return HostAddresses.toArray(new String[0]);
}

Now I want to translate using Lamba Stream Java 8 based on. Here my code:

try {

  Collections.list(NetworkInterface.getNetworkInterfaces())
      .stream()
      .filter(ni -> !ni.isLoopback())  //unreported exception SocketException; must be caught or declared to be thrown
      .filter(ni -> ni.isUp())  //unreported exception SocketException; must be caught or declared to be thrown
      .filter(ni -> ni.getHardwareAddress() != null)  //unreported exception SocketException; must be caught or declared to be thrown
      .flatMap(ni -> ni.getInterfaceAddresses().stream())
      .filter(ia -> ia.getBroadcast() != null)
      .forEach(ia -> HostAddresses.add(ia.getAddress().getHostAddress()));

} catch (SocketException e) {
  System.out.println(e.getMessage());
}

But When I change to use Try catch...

    try {
      Collections.list(NetworkInterface.getNetworkInterfaces())
          .stream()
          .filter(ni -> {  //incompatible types: bad return type in lambda expression missing return value
            try {
              !ni.isLoopback(); //not a statement cannot find symbol symbol:   method isLoopback() location: variable ni of type T where T is a type-variable: T extends Object declared in interface Stream
            } catch (SocketException ex) {  //exception SocketException is never thrown in body of corresponding try statement
              Logger.getLogger(JPanelServerClient.class.getName()).log(Level.SEVERE, null, ex);
            }
          })
          .filter(ni -> ni.isUp())
          .filter(ni -> ni.getHardwareAddress() != null)
          .flatMap(ni -> ni.getInterfaceAddresses().stream())
          .filter(ia -> ia.getBroadcast() != null)
          .forEach(ia -> HostAddresses.add(ia.getAddress().getHostAddress()));

    } catch (SocketException e) {
      System.out.println(e.getMessage());
    }

According to tip @Jacob-G this solve the problem (But he has reason with "Not everything has to be functional")

try {
  Collections.list(NetworkInterface.getNetworkInterfaces())
  .stream()
  .filter(ni -> {
    try {
      return !ni.isLoopback();
    } catch (SocketException ex) {
      System.out.println(ex.getMessage());
      return false;
    }
  })
  .filter(ni -> {
    try {
      return ni.isUp();
    } catch (SocketException ex) {
      System.out.println(ex.getMessage());
      return false;
    }
  })
  .filter(ni -> {
    try {
      return ni.getHardwareAddress() != null;
    } catch (SocketException ex) {
      System.out.println(ex.getMessage());
      return false;
    }
  })
  .flatMap(ni -> ni.getInterfaceAddresses().stream())
  .filter(ia -> ia.getBroadcast() != null)
  .forEach(ia -> HostAddresses.add(ia.getAddress().getHostAddress()));
} catch (SocketException e) {
  System.out.println(e.getMessage());
}

How I can translate it (simpler)? How I can translate it?

joseluisbz
  • 1,491
  • 1
  • 36
  • 58
  • 2
    **Not everything has to be functional**. To fix your issue with your last example, change `!ni.isLoopback();` to `return !ni.isLoopback();` since the `Predicate` must return a `boolean`. Although, you'll need to return a value in the exception as well, or throw an exception. – Jacob G. Nov 04 '17 at 04:53
  • To make the code closer to functional-style codes, you can also wrap the methods with exceptions in a helper function and then directly use the helper function in the functional parts of your code. – jrook Nov 04 '17 at 04:59

1 Answers1

0

Unfortunately dealing with checked exceptions in java streams is ugly. You have to create a separate function which takes the predicate(filter operation) catch any checked exception, rethrow it as runtime exception

For the lack of my imagination, consider the following two functions which you have no control of(think part of a library or jdk):

boolean isEven(int i) throws IOException {
    return i % 2 == 0;
}

boolean isOdd(int i) throws IOException {
    return i % 2 == 1;
}

Stream.of(1, 2, 3, 4, 5)
        .filter(i -> isEven(i))// compilation error
        .filter(i -> isOdd(i))// compilation error
        .collect(Collectors.toList());

Approach 1: Write a wrapper method for each of two functions and handle the exceptions there:

boolean isEvenWrapper(int i){
  try{
    return isEven(i);
   } catch (IOException ex){
     throw new UnCheckedIOException(ex);
}

And then your stream looks like:

Stream.of(1, 2, 3, 4, 5)
        .filter(i -> isEvenWrapper(i)) 
        .filter(i -> isOddWrapper(i))          //compiles and runs.
        .collect(Collectors.toList());

Approach 2: Approach 1 is easy if we have 1 or 2 filter functions, but if we have more filter functions, writing a wrapper function for each throwable method becomes tedious.

We need to create a Functional Interface for a predicate which throws exception.

@FunctionalInterface
public interface CheckedPredicate<T> {
    boolean test(T t) throws Throwable;
}

And another Predicate or method which takes this CheckedPredicate and safely evaluates it.

public static <T> Predicate<T> uncheckedPredicate(CheckedPredicate<T> predicate) {
    return t -> {
        try {
            return predicate.test(t);
        } catch (Throwable x) {
            throw new RuntimeException(x);
        }
    };
}

And now our stream becomes,

Stream.of(1, 2, 3, 4, 5)
        .filter(uncheckedPredicate(i -> isEven(i)))
        .filter(uncheckedPredicate(i -> isOdd(i)))  //compiles and runs.
        .collect(Collectors.toList());

The approach 2 functionality which I have described, is provided by JOOL and specifically by this class Unchecked

mitra
  • 182
  • 11