【发布时间】:2016-02-19 06:05:09
【问题描述】:
是否有在 Stream 中改变元素的“最佳实践”?我特别指的是流管道内的元素,而不是它之外的元素。
例如,考虑我想要获取用户列表、为空属性设置默认值并将其打印到控制台的情况。
假设用户类:
class User {
String name;
static User next(int i) {
User u = new User();
if (i % 3 != 0) {
u.name = "user " + i;
}
return u;
}
}
在 java 7 中,它类似于:
for (int i = 0; i < 7; i++) {
User user = User.next(i);
if(user.name == null) {
user.name = "defaultName";
}
System.out.println(user.name);
}
在 java 8 中,我似乎会使用 .map() 并返回对变异对象的引用:
IntStream.range(0, 7)
.mapToObj(User::next)
.map(user -> {
if (user.name == null) {
user.name = "defaultName";
}
return user;
})
//other non-terminal operations
//before a terminal such as .forEach or .collect
.forEach(it -> System.out.println(it.name));
有没有更好的方法来实现这一点?也许使用 .filter() 来处理空突变,然后连接未过滤的流和过滤的流?一些巧妙的使用 Optional?目标是能够在终端 .forEach() 之前使用其他非终端操作。
在流的“精神”中,我试图在没有中间集合和不依赖管道外部副作用的简单“纯”操作的情况下做到这一点。
编辑:官方 Stream java doc 声明'少量流操作,例如 forEach() 和 peek(),只能通过副作用进行操作;这些应该小心使用。鉴于这将是一个不干扰的操作,是什么让它特别危险?我看到的示例超出了管道,这显然是粗略的。
【问题讨论】:
-
“是否有‘最佳实践’来改变 Stream 中的元素?”。是的:不要。
-
这种用法明显滥用
map()。在forEach()中做你的突变。 -
如果我要在 .forEach() 中执行此操作,那么我如何获得对收集到的 User 对象的引用以执行其他工作?
标签: java java-8 java-stream