Java 8 modify stream elements

对着背影说爱祢 提交于 2020-01-30 20:00:10

问题


I wanted to write pure function with Java 8 that would take a collection as an argument, apply some change to every object of that collection and return a new collection after the update. I want to follow FP principles so I dont want to update/modify the collection that was passed as an argument.

Is there any way of doing that with Stream API without creating a copy of the original collection first (and then using forEach or 'normal' for loop)?

Sample object below and lets assume that I want to append a text to one of the object property:

public class SampleDTO {
    private String text;
}

So I want to do something similar to below, but without modifying the collection. Assuming "list" is a List<SampleDTO>.

list.forEach(s -> {
    s.setText(s.getText()+"xxx");
});

回答1:


You must have some method/constructor that generates a copy of an existing SampleDTO instance, such as a copy constructor.

Then you can map each original SampleDTO instance to a new SampleDTO instance, and collect them into a new 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());



回答2:


To make this more elegant way I would suggest create a Method with in the class.

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

and add it like:

List<SampleDTO> output =list.stream().map(SampleDTO::getSampleDTO).collect(Collectors.toList();



回答3:


Streams are immutable like strings so you cannot get around needing to create a new stream/list/array

That being said you can use .Collect() to return a new collection post change so

List<Integer> result = inList.stream().map().Collect()



回答4:


I think it would be better, especially if doing multi-threaded work, to stream the original list into a new modified list or whatever else is desired.

The new list or map or whatever other structure you desire can be created as part of the streaming process.

When the streaming process is completed, simply swap the original with the new.

All of this should occur in a synchronized block.

In this manner, you get the maximum performance and parallelism for the reduce or whatever it is you are doing, and finish with an atomic swap.



来源:https://stackoverflow.com/questions/38302531/java-8-modify-stream-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!