Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Construct object from multiples sources java 8 with custom function

I have multiples sources (Maps) where i store data related to different attributes destined to contruct a final object with an id. These maps have different structures according this pattern :

Map

  • id is the identifier of my final object FinalObject
  • X1, X2 are attributes of my final object FinalObject

in real code i have several map as following :

Map<Integer, String> descriptions;
Map<Integer, Double> prices;
Map<Integer, Double> quantities;
Map<Integer, String> currencies;

I can merge the stream of my collections with Stream.of() but i have two issues to deal with, the structure of heterogenous maps and an also for each entry i want to create a Final object in a Java8 manner.

I think of my MultipleFunction as BiFunction my defined attributes for the FinalObject as arguments. Is it okay as a design ?

Any opionions or advises?

The result of the merging would be like this :

Stream.of(descriptions.entrySet(), prices.entrySet(), quantities.entrySet(), currencies.entrySet())
        .flatMap(Set::stream)
        .collect(Collectors.toMap(Map.Entry::getKey, entry -> new FinalObject(description, price, quantity, currency)));

This code don't compile and is for my problem better comprehension.

like image 983
Hassam Abdelillah Avatar asked Jan 26 '23 11:01

Hassam Abdelillah


2 Answers

Get a stream of the id numbers...

descriptions.keySet().stream()

...then look up the ids in the four maps:

descriptions.keySet().stream()
    .map(id -> {
         String description = descriptions.get(id);
         Double price       = prices      .get(id);
         Double quantity    = quantities  .get(id);
         String currency    = currencies  .get(id);

         return new FinalObject(description, price, quantity, currency);
    });

This assumes that descriptions has an entry for every single id. If not, adjust it as you see fit.

If you wish you could save one lookup by iterating over entrySet() instead of keySet().

descriptions.entrySet().stream()
    .map(e -> {
         int id = e.getKey();

         String description = e.getValue();
         Double price       = prices    .get(id);
         Double quantity    = quantities.get(id);
         String currency    = currencies.get(id);

         return new FinalObject(description, price, quantity, currency);
    });
like image 107
John Kugelman Avatar answered Jan 30 '23 13:01

John Kugelman


Let's suppose the FinalObject is immutable and has the following structure:

public static class FinalObject {

    private final String description;
    private final Double price;
    private final Double quantity;
    private final String currency;

    // constructor

Firstly create a set with all the ids from the maps. By the Set characteristics, the values are distinct:

final Set<Integer> idSet = new HashSet<>();
idSet.addAll(descriptions.keySet());
idSet.addAll(prices.keySet());
idSet.addAll(quantities.keySet());
idSet.addAll(currencies.keySet());

Then you can use the java-stream in a quite neat and simple way to construct the objects:

final List<FinalObject> list = idSet.stream()
    .map(id -> new FinalObject(
            descriptions.get(id),
            prices.get(id),
            quantities.get(id),
            currencies.get(id)))
    .collect(Collectors.toList());
like image 28
Nikolas Charalambidis Avatar answered Jan 30 '23 13:01

Nikolas Charalambidis