Ada*_*ord 7 java java-8 java-stream
是否有一个"最佳实践"来改变流中的元素?我特指的是流管道中的元素,而不是它之外的元素.
例如,考虑我想获取用户列表,为null属性设置默认值并将其打印到控制台的情况.
假设User类:
class User {
String name;
static User next(int i) {
User u = new User();
if (i % 3 != 0) {
u.name = "user " + i;
}
return u;
}
}
Run Code Online (Sandbox Code Playgroud)
在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);
}
Run Code Online (Sandbox Code Playgroud)
在java 8中,我似乎使用.map()并返回对mutated对象的引用:
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));
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来实现这一目标?也许使用.filter()来处理null变异然后连接未过滤的流和过滤的流?有些巧妙使用Optional?目标是在终端.forEach()之前使用其他非终端操作的能力.
在流的"精神"中,我试图在没有中间集合和简单的"纯粹"操作的情况下执行此操作,这些操作不依赖于管道外的副作用.
编辑:官方流java文档声明'少量流操作,如forEach()和peek(),只能通过副作用操作; 这些都应该小心使用.鉴于这将是一个不干扰的操作,具体是什么使它危险?我见过的例子到达管道之外,这显然是粗略的.
不要改变对象,直接映射到名称:
IntStream.range(0, 7)
.mapToObj(User::next)
.map(user -> user.name)
.map(name -> name == null ? "defaultName" : name)
.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
听起来您正在寻找peek:
.peek(user -> {
if (user.name == null) {
user.name = "defaultName";
}
})
Run Code Online (Sandbox Code Playgroud)
...虽然不清楚您的操作实际上是否需要修改流元素,而不是仅仅通过您想要的字段:
.map(user -> (user.name == null) ? "defaultName" : user.name)
Run Code Online (Sandbox Code Playgroud)