方法链接好吗?
我不是反对使用很多方法链接的函数式编程,而是反对人们无意识地追赶新事物的羊群思想。
示例,如果我正在使用流编程处理项目列表,并且需要找出导致抛出NullPointerException
的确切行。
private void test() {
List<User> aList = new ArrayList<>();
// fill aList with some data
aList.stream().forEach(x -> doSomethingMeaningFul(x.getAddress()));
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
因此,在上面的示例中,如果列表中的任何对象为null,则在调用NullPointerException
时将导致x.getAddress()
并退出,而没有给我们提供钩子来标识存在此问题的用户记录
在流编程中,我可能缺少提供此功能的功能,感谢您的帮助。
编辑1: NPE只是一个示例,但是可能还会发生其他几种RuntimeException。编写过滤器实质上意味着根据我正在执行的操作检查每个RTE条件。而且检查所有操作都会很痛苦。
要更好地了解我的意思,下面是使用较旧方法的代码段;我找不到与流/函数式编程方法同等的东西。
List<User> aList = new ArrayList<>();
// Fill list with some data
int counter = 0;
User u = null;
try {
for (;counter < aList.size(); counter++) {
u = aList.get(counter);
u.doSomething();
int result = u.getX() / u.getY();
}
} catch(Exception e) {
System.out.println("Error processing at index:" + counter + " with User record:" + u);
System.out.println("Exception:" + e);
}
This will be a boon during the maintenance phase(longest phase) pointing exact data related issues which are difficult to reproduce.
**Benefits:**
- Find exact index causing issue, pointing to data
- Any RTE is recorded and analyzed against the user record
- Smaller stacktrace to look at
答案 0 :(得分:1)
方法链接好吗?
通常,简单的答案是:取决于情况。
当您
然后确定,连锁电话。
如果没有明确满足上述任何条件,请考虑不这样做。
无论如何,将您的方法调用分布在新行上可能会有所帮助。像IntelliJ这样的工具实际上会为您提供每一行的高级类型信息(嗯,并非总是如此,请参阅我自己的question;)
从不同的角度来看:对于编译器,链接调用并不重要。这实际上仅对人类重要。为了提高可读性,或者在调试过程中。
答案 1 :(得分:0)
在您的test()函数中,您正在创建一个空列表List<User> aList = new ArrayList<>();
在上面做每个。首先向
添加一些元素aList
如果您要处理空值,可以在foreach之前添加.filter(x-> x != null)
,这样会过滤掉所有空值
下面是代码
private void test() {
List<User> aList = new ArrayList<>();
aList.stream().filter(x-> x != null).forEach(x -> doSomethingMeaningFul(x.getAddress()));
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
答案 2 :(得分:0)
您可以在流中编写黑色代码。而且,您可以找到可能导致 NullPointerException 的列表项。我希望这段代码对您有所帮助
private void test() {
List<User> aList = new ArrayList<>();
aList.stream().forEach(x -> {
if(x.getAddress() != null)
return doSomethingMeaningFul(x.getAddress())
else
system.out.println(x+ "doesn't have address");
});
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
如果需要,可以在 部分中抛出 NullPointerException 或诸如 AddressNotFoundException 之类的自定义专有内容
答案 3 :(得分:0)
这有几个方面。
1)空值
最好永远不要分配null来避免检查null的问题。无论是否进行函数式编程,这都适用。不幸的是,许多库代码确实暴露了返回空值的可能性,但是试图通过在一个地方处理它来限制对此值的暴露。
不管您是否正在执行FP,如果您在调用自己的方法时都不必编写null检查,您会发现沮丧的程度会减少,因为您自己的方法永远不会返回null。
可能为null的变量的替代方法是使用Java 8的Optional
类。
代替:
public String myMethod(int i) {
if(i>0) {
return "Hello";
} else {
return null;
}
}
要做:
public Optional<String> myMethod(int i) {
if(i>0) {
return Optional.of("Hello");
} else {
return Optional.empty();
}
查看Optional
Javadoc,以了解这如何迫使调用者考虑发生Optional.empty()
响应的可能性。
作为“ null代表不存在”和“ Optional.empty()
代表不存在”之间的桥梁,可以使用Optional.ofNullable(val)
,当Empty
时返回val == null
。但是请记住,Optional.empty()
和Optional.of(null)
是不同的值。
2)例外
的确,在流处理程序中引发异常不是很好。异常不是非常适合FP的机制。 FP友好的替代方案是Either
,它不是Java的标准组成部分,但易于编写或在第三方库中找到:Is there an equivalent of Scala's Either in Java 8?
public Either<Exception, Result> meaningfulMethod(Value val) {
try {
return Either.right(methodThatMightThrow(val));
} catch (Exception e) {
return Either.left(e);
}
}
...然后:
List<Either<Exception, Result>> results = listOfValues.stream().map(meaningfulMethod).collect(Collectors.toList());
3)索引
在使用List
制成的流时,您想知道流元素的索引吗?参见Is there a concise way to iterate over a stream with indices in Java 8?