Zyg*_*yga 14 java java-8 java-stream
我想用Java 8编写纯函数,将集合作为参数,对该集合的每个对象应用一些更改,并在更新后返回一个新集合.我想遵循FP原则,所以我不想更新/修改作为参数传递的集合.
有没有办法使用Stream API而不先创建原始集合的副本(然后使用forEach或'normal'for循环)?
下面的示例对象,并假设我想将文本追加到其中一个对象属性:
public class SampleDTO {
private String text;
}
Run Code Online (Sandbox Code Playgroud)
所以我想做类似下面的事情,但不修改集合.假设"列表"是一个List<SampleDTO>.
list.forEach(s -> {
s.setText(s.getText()+"xxx");
});
Run Code Online (Sandbox Code Playgroud)
Era*_*ran 23
您必须有一些方法/构造函数来生成现有SampleDTO实例的副本,例如复制构造函数.
然后你可以将map每个原始SampleDTO实例添加到一个新SampleDTO实例,并将collect它们变成一个新实例List:
List<SampleDTO> output =
list.stream()
.map(s-> {
SampleDTO n = new SampleDTO(s); // create new instance
n.setText(n.getText()+"xxx"); // mutate its state
return n; // return mutated instance
})
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
为了使这种方式更加优雅,我建议Method在类中创建一个 with 。
public class SampleDTO {
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public SampleDTO(String text) {
this.text = text;
}
public SampleDTO getSampleDTO() {
this.setText(getText()+"xxx");
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
并将其添加为:
List<SampleDTO> output =list.stream().map(SampleDTO::getSampleDTO).collect(Collectors.toList();
Run Code Online (Sandbox Code Playgroud)
我认为更干净、更易读的解决方案是:
List<SampleDTO> unmodifiable = Arrays.asList(new SampleDTO("1"), new SampleDTO("2"));
List<SampleDTO> modified = unmodifiable.stream()
.map(s -> new SampleDTO(s.getText())) // '.map(SampleDTO::new)' with copy constructor
.peek(s -> s.setText(s.getText() + "xxx"))
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
或者,如果您有 SampleDTO 的复制构造函数,您可以将map函数替换为.map(SampleDTO::new).
peek函数将在不更改 Stream 的结果类型的情况下对 Stream 的元素提供操作。
| 归档时间: |
|
| 查看次数: |
36803 次 |
| 最近记录: |