Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generalize approach to validate the null in the object parameters

I am trying to implement a logic where I have a POJO class which has 7 attributes. I have added these POJO classes into the map depends upon the value of the attributes.

Below is the implementation

Map<String,List<PriceClass>> map = new HashMap();
for (PriceClass price : prices) {
  if (price.getAttribute1() !=null) {
      if (map.get("attribute1") !=null) {
             map.get("attribute1").add(price);
      } else {
           map.set("attibute1",Collections.singletonList(price))
      }
   } else if(price.getAttribute2()!=null) {
       if (map.get("attribute12") !=null) {
             map.get("attribute2").add(price);
       } else {
           map.set("attibute2",Collections.singletonList(price))
       }
   } else if (price.getAttribute3() !=null) {
     .
     .
     .
   } else if (price.getAttribute7() !=null) {
       //update the map
   }
}

My question is rather than writing these many if loops are there any generalize implementations I can try here.

like image 300
sree Avatar asked Apr 12 '26 12:04

sree


2 Answers

You may use

Map<String,List<PriceClass>> map = new HashMap<>();
for(PriceClass price: prices) {
    HashMap<String,Object> options = new HashMap<>();
    options.put("attibute1", price.getAttribute1());
    options.put("attibute2", price.getAttribute2());
    options.put("attibute3", price.getAttribute3());
    options.put("attibute4", price.getAttribute4());
    options.put("attibute5", price.getAttribute5());
    options.put("attibute6", price.getAttribute6());
    options.put("attibute7", price.getAttribute7());
    options.values().removeIf(Objects::isNull);
    options.keySet().forEach(attr -> map.computeIfAbsent(attr, x -> new ArrayList<>())
                                        .add(price));
}

or generalizing the process:

Prepare a unmodifiable map once

static final Map<String, Function<PriceClass,Object>> ATTR;
static {
  Map<String, Function<PriceClass,Object>> a = new HashMap<>();
  a.put("attibute1", PriceClass::getAttribute1);
  a.put("attibute2", PriceClass::getAttribute2);
  a.put("attibute3", PriceClass::getAttribute3);
  a.put("attibute4", PriceClass::getAttribute4);
  a.put("attibute5", PriceClass::getAttribute5);
  a.put("attibute6", PriceClass::getAttribute6);
  a.put("attibute7", PriceClass::getAttribute7);
  ATTR = Collections.unmodifiableMap(a);
}

and use either

Map<String,List<PriceClass>> map = new HashMap<>();
for(PriceClass price: prices) {
    HashMap<String,Object> options = new HashMap<>();
    ATTR.forEach((attr,func) -> options.put(attr, func.apply(price)));
    options.values().removeIf(Objects::isNull);
    options.keySet().forEach(attr -> map.computeIfAbsent(attr, x -> new ArrayList<>())
                                        .add(price));
}

or

Map<String,List<PriceClass>> map = prices.stream()
    .flatMap(price -> ATTR.entrySet().stream()
        .filter(e -> e.getValue().apply(price) != null)
        .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), price)))
    .collect(Collectors.groupingBy(Map.Entry::getKey,
                Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
like image 80
Holger Avatar answered Apr 14 '26 00:04

Holger


A likely optimal solution would be similar to one I have suggested earlier today.

Use the Map<String, Optional<?>> to store the Optional values of the checked attributes with a key of the future output map key.

Map<String, Optional<?>> options = new HashMap<>();
options.put("attribute1", Optional.ofNullable(price.getAttribute1()));
// ...
options.put("attribute3", Optional.ofNullable(price.getAttribute2()));
// ...

Using the iteration of the indices would let you perform the update of a map.

Map<String,List<Price>> map = new HashMap();
for (int i=1; i<7; i++) {                                      // attributes 1..7
    String attribute = "attribute" + i;                        // attribute1...attribute7
    options.get(attribute).ifPresent(any ->                    // for non-nulls
               map.put(                                        // put to the map
                   attribute,                                  // attribute as key remains
                   Optional.ofNullable(map.get(attribute))     // gets the existing list
                           .orElse(new ArrayList<>())          // or creates empty
                           .add(price)));                      // adds the current Price
}

Moreover, I bet your intention was a bit different. There is no method Map::set

map.set("attibute1",Collections.singletonList(price))

Didn't you mean to put a List<Price> with one item to the very same key instead?

map.put("attibute1", Collections.singletonList(price))

For this reason you can use the way I posted above.

like image 25
Nikolas Charalambidis Avatar answered Apr 14 '26 02:04

Nikolas Charalambidis