简体   繁体   中英

Java lambda stream merge parameters in model

I cant find answer. I try to merge multiple Object to one. Example model

public class Model {
    private List<Map<String, Object>> param1;
    private List<String> param2;
}

In my code, I convert another data to model.

List<Model> models = models2.stream()
    .map(Optional::get)
    .map(model2 -> convert(model2))
    .collect(Collectors.toList()); 

I try to aggregate converted list of models to one Model. Like:

Model model = models2.stream() ...etc

but I dont know how.

The easiest is to add a merge method to your Model class:

public class Model {
    private List<HashMap<String, Object>> param1;
    private List<String> param2;

    public Model merge (Model other) {
        this.param1.addAll(other.param1);
        this.param2.addAll(other.param2);

        return this;
    }
}

And then reduce your stream:

Model allInOne = models2.stream()
    .map(Optional::get)
    .map(model2 -> convert(model2))
    .reduce(Model::merge)
    .get();

That merge method can also be a static Model merge (Model first, Model second) or externalized BinaryOperator<Model> function.

First of all your current code contains a hidden unobvious bug . The operation Optional::get will throw an exception when an empty Optional met. You should filter out the empty optionals first:

// ...
.filter(Optional::isPresent)
.map(Optional::get)
// ...

Or if you're using java-9 or above you can simply flat-map the optional values:

// ...
.flatmap(Optional::stream)
// ...   

As for your question, it looks like you need to reduce with a merge-function . There are different ways to define that function:

  1. Method reference:

     private Model merge(Model model1, Model model2) { // merge model2 to model1 return model1; } Model model = models2.stream() .filter(Optional::isPresent) .map(Optional::get) .map(this::convert) .reduce(this::merge) .orElse(defaultModel); 
  2. A BinaryOperator stored in a variable:

     BinaryOperator<Model> merge = (model1, model2) -> { /* do smth */; return model1;} // ... .map(this::convert) .reduce(merge) // 
  3. Inline lambda

     // ... .map(this::convert) .reduce((model1, model2) -> { /* do smth */; return model1;}) // 

IMHO the first option is the best one. Having a separate method will make your code cleaner and easier to maintain.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM