Home > front end >  Java Merge 2 HashMap without null values
Java Merge 2 HashMap without null values

Time:04-05

I know that this question has been already posted. But after many days searching a solution, i can't find one..

I have two objects, which are converted to HashMap. Once these HashMap I need to merge object 1 into object 2. Namely: These objects can contain null keys.

I want the attribute of object 1 to replace the attribute of object 2 only if the attribute of object 1 is not null.


private <T> Map<String, T> mergeObjects(T first, T second) {
        ObjectMapper oMapper = new ObjectMapper();

        // On transforme l'objet en une MAP afin de faciliter le merge
        Map<String, T> objet1Map = oMapper.convertValue(first, Map.class);
        Map<String, T> objet2Map = oMapper.convertValue(second, Map.class);


        // Merge object 1 into object 2 (but it merges null values, i don't want that..)
        objet2Map.putAll(objet1Map);

        return objet2Map;
    }


My object is something like that :

{
        "environment": "d",
        "type": "deploymentconfig",
        "component": {
            "template": "redis-template.yaml",
            "routes": null,
            "parameters": {
                "REQUESTS_CPU": "25m",
                "LIMITS_MEMORY": null,
                "PROBE_PATH": null,
                "IMAGE_STREAM": "my-image",
                "IMAGE_STREAM_TAG": "6.9.6"
}
...
...
}

Edit 1 :

objet1 : {component={template=redis-pvc-component-template.yaml, parameters={REQUESTS_CPU=25m, IMAGE_STREAM=redis-5-rhel7-gtec, IMAGE_STREAM_TAG=5.16_19.12, MEMORY_LIMIT=298Mi}}, type=deploymentconfig}

objet2: {component={parameters={STORAGECLASS=prod}}, environment=p, type=deploymentconfig}

Result ->

{
        "environment": "p",
        "type": "deploymentconfig",
        "component": {
            "template": null,
            "routes": null,
            "parameters": {
                "REQUESTS_CPU": null, // disappeared
                "LIMITS_MEMORY": null,
                "PROBE_PATH": null,
                "IMAGE_STREAM": null, // disappeared
                "IMAGE_STREAM_TAG": null, // disappeared
                "MEMORY_LIMIT": null, // disappeared
                "STORAGECLASS": "prod",
                "VOLUME": null,
                "ROUTE_HOSTNAME": null,
                "IMAGE_STREAM_PROJECT": null,
                "LIVENESS_PROBE_PATH": null,
                "LIVENESS_PROBE_DELAY": null,
                "READINESS_PROBE_PATH": null,
                "READINESS_PROBE_DELAY": null,
                "JAVA_OPTIONS": null,
                "ENVIRONMENT": null
            }
        },
        "autoscaler": null
    }



As you can see many properties have disappeared after the putAll..

CodePudding user response:

Edit 1:

    @Test
    public void test() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(Include.NON_NULL);

        HashMap<String,String> map = new HashMap<>();

        map.put("some","some");
        map.put("other",null);

        HashMap<String,Object> othermap = new HashMap<>();
        othermap.put("keey","value");
        othermap.put("nested",map);

        final String asString = objectMapper.writeValueAsString(othermap);
        System.out.println(asString);
    }
}

without serialization config.

{"keey":"value","nested":{"some":"some","other":null}}.

with serialization config.

{"keey":"value","nested":{"some":"some"}} //non null inclusion.


Can you try setting objectmapper to exclude null properties?

mapper.setSerializationInclusion(Include.NON_NULL);

https://www.baeldung.com/jackson-ignore-null-fields#globally

CodePudding user response:

You'll need to merge the individual entries of the maps.

If you just want to keep the value of the first map, you can just use putIfAbsent().

Map<String, T> map1 = ...
Map<String, T> map2 = ...
Map<String, T> result = new HashMap<>(map1);

map2.forEach((key, value) -> result.putIfAbsent(key, value);

If you have the value in both maps, you can use merge to define behavior to calculate what value you want.

map2.forEach((key, value) -> result.merge(key, value, // put if absent
   (v1, v2) -> v1); // calculate new value if present in both
}

The latter example I give behaves equivalent to the first, ie it keeps the existing value in the map.

  • Related