Lambda嵌套流按方法筛选,出现异常



我回答了这个问题

这是代码:

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

方法!

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]);
}

现在我想使用基于的LambaStreamJava8进行翻译。这是我的代码:

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());
}

但当我改为使用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());
}

根据@Jacob-G的提示,这解决了问题(但他有理由说"不是所有东西都必须是功能性的")

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());
}

我该怎么翻译(更简单)?如何翻译

不幸的是,在java流中处理已检查的异常非常糟糕。您必须创建一个单独的函数,该函数接受谓词(过滤操作)捕获任何已检查的异常,并将其作为运行时异常重新抛出

由于我缺乏想象力,请考虑以下两个你无法控制的功能(想想库或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());

方法1:为两个函数中的每一个编写一个包装器方法,并处理其中的异常:

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

然后你的流看起来像:

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

方法2:如果我们有1或2个过滤函数,方法1很容易,但如果我们有更多的过滤函数,为每个可丢弃的方法编写包装函数就会变得乏味。

我们需要为抛出异常的谓词创建一个函数接口。

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

以及另一个谓词或方法,它接受这个CheckedPredicate并安全地评估它。

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

现在我们的流变成了

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

我所描述的方法2功能由JOOL提供特别是这个类别未选中的

最新更新