Home > Blockchain >  How to defer creating objects stored in Map as values only when the key is fetched
How to defer creating objects stored in Map as values only when the key is fetched

Time:08-05

We had a factory method like below, which worked fine, but when the case statements increased, We had issues with SONAR.

public Message create(int uuid) {
switch (uuid) {
  case FIRST_MESSAGE_ID:
    return new FirstMessage();
    .
  case SECOND_MESSAGE_ID:
    return new SecondMessage();
    .
  default:

      return null;
}}

To avoid the SONAR complaints we moved the object creation to a map.

public Message create(int uuid) {
Map<Integer, Message> map = new HashMap<>();
map.put(FIRST_MESSAGE_ID, new FirstMessage());
.
.
.
map.put(SECOND_MESSAGE_ID, new SecondMessage());
}
if(map.containsKey(uuid)){
return map.get(uuid);
}
return null;
}

The only drawback of this is that every time when I try creating objects using create(int uuid), the whole "map" is initialized every time with all my 100 objects. Is there any way to defer creating objects only when the key is fetched? Or any other optimized way to solve this issue.

Edit: I need a new instance of objects everytime

Can we use lambda functions here to fetch new object everytime only when the key is fetched?

CodePudding user response:

If there are fixed set of uuid and Message object pairs, make the Map a static final variable and move out of the method, instead of placing it inside method. Like below:

class Main {
  static final Map<String, Message> messageMap = Map.of(
     FIRST_MESSAGE_ID, new FirstMessage(),
     .
     .
     .
     SECOND_MESSAGE_ID, new SecondMessage()
   );
}

usage:

Main.messageMap.get(uuid);

CodePudding user response:

You may create a map of uuid to Supplier instead, so that you only need to create a readonly static unmodified map once. After geting the supplier by the uuid from the map you simply call the get() method to get a new instance. I think this matches the "defer creating object" you expect.

Supplier references:

CodePudding user response:

Perhaps the following will work for you:

  • create an instance of the map but initialize it upon first call of create().
  • If the message isn't found, return a default message.
  • This will work whether the map is declared static or not, but it does defer the creation as required.
  • you can also move the creation code outside the create() method but it will be created when the class is initialized.
Map<Integer, Message> map = null;
public Message create(int uuid) {       
    if (map == null) {
         map = new HashMap<>();         
         map.put(FIRST_MESSAGE_ID, new FirstMessage());
         .
         map.put(SECOND_MESSAGE_ID, new SecondMessage());    
         ...     
     }
     return map.getOrDefault(uuid, someDefaultMessage);
}
  • Related