1

What is the best way to create a new object based on two different objects.

I would like to use java streams.

My two start objects

public class EventA{
    Long id;
    String name;
    ...
    Long locationID;
}

public class EventB{
    Long id
    String Name;
    ...
    Long locationID;
}

And my result class

public class Result{
    Long locationID;
    String eventAName;
    String eventBName;

    public Result(...){...}
}

I have two object arrays like

List<EventA> eventAList;
List<EventB> eventBList;

I like to get an array of Result objects. Every EventA name should be copied to the resultList. If an EventB at the same location exists I would like to save the name in eventBName.

All I have done so far is

List<Result> resultList = eventAList.stream().map(e -> new Result(e.locationID, e.name, null)).collect(Collectors.toList());

I don't know how to pass the value from EventB to the constructor

4
  • Can't you just have a common ancestor to EventA and EventB, since they display practically identical properties? You'd then hjave a List<EventCommon> to stream... Commented Jun 23, 2016 at 8:54
  • No, it's just to simplify my example. In fact they are completely different Commented Jun 23, 2016 at 8:55
  • What do you mean by "at the same location" ? Same locationID or "at the same index in eventAList and eventBList" ? Commented Jun 23, 2016 at 9:08
  • resultList should be as big as eventAList. If the location matches (same locationID) I would like to save the name of EventB inside eventBName of the result object. Commented Jun 23, 2016 at 9:12

3 Answers 3

3

When creating your Result, you can use a stream to iterate on the values in eventBList to retain only the ones with the same locationID as your eventAList value, then take the value you found, and map() it to it's Name value, or null if it doesn't exists:

List<Result> resultList = eventAList.stream().map(a -> new Result(a.locationID, a.name,
    eventBList.stream().filter(b -> b.locationID.equals(a.locationID)).findAny().map(b -> b.Name).orElse(null)
)).collect(Collectors.toList());

For better performances, you can use a temporary Map:

final Map<Long, String> eventBMap = eventBList.stream().collect(Collectors.toMap(b -> b.locationID, b -> b.Name));

List<Result> resultList = eventAList.stream().map(a -> new Result(a.locationID, a.name,
    eventBMap.get(a.locationID)
)).collect(Collectors.toList());
Sign up to request clarification or add additional context in comments.

Comments

1

I found a working way

I adjust the constructor of the Result class to

public Result(Long locationID, String eventAName, EventB eventB){
    this.locationID = locationID;
    this.eventAName = eventAName;
    this.eventBName = eventB.name;
}

and then inside my java stream

List<Result> resultList = eventAList.stream().map(ea -> new Result(ea.locationID, ea.name, eventBList.stream().filter(eb -> eb.locationID.equals(ea.locationID)).findFirst().orElse(new EventB()).get()).collect(Collectors.toList());

Comments

1

You can do something like the following and work on enhancements afterwards (e.g. create a map for eventBlist by locationId as key in order to have faster search)

Function<EventA, SimpleEntry<EventA, Optional<EventB>>> mapToSimpleEntry = eventA -> new SimpleEntry<>(eventA,
    eventBList.stream()
    .filter(e -> Objects.equals(e.getLocationID(), eventA.getLocationID()))
    .findFirst());

Function<SimpleEntry<EventA, Optional<EventB>>, Result> mapToResult = simpleEntry -> {
    EventA eventA = simpleEntry.getKey();
    Optional<EventB> eventB = simpleEntry.getValue();
    return new Result(eventA.getLocationID(), eventA.getName(), eventB.map(EventB::getName).orElse(null));
};

eventAList.stream()
    .map(mapToSimpleEntry)
    .map(mapToResult)
    .collect(Collectors.toList());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.