Reputation: 2683
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
Upvotes: 1
Views: 10128
Reputation: 1244
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());
Upvotes: 1
Reputation: 2683
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());
Upvotes: 1
Reputation: 11920
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());
Upvotes: 3