Search code examples
javadictionaryhashmapjava-stream

Compare two HashMaps with the Java streams API and replace attributes values in one HashMap


I have 2 hashmaps

HashMap<DedupeTableEntity,List<DedupeTableEntity>> deltaHashmap 

HashMap<DedupeTableEntity,List<DedupeTableEntity>> existingHashmap 

 DedupeTableEntity has an id, country, entity_flag as attributes

  • I want to iterate through the values of delta hash map (both hashmaps has only 1 key and list of values under that key)

  • Check whether that object is in existing hash map if 2 attributes match (country and id)

  • If it exists  

  • Take attribute value of (entity flag) that object from existinghashmap and replace the attribute (entity flag) value of the same object in the delta hash map

    public void compareTwoHashmaps(HashMap<DedupeTableEntity,List<DedupeTableEntity>> deltaHashmap 
    , HashMap<DedupeTableEntity,List<DedupeTableEntity>> existingHashmap){
            //iterate through deltahashmap values
            return deltaHashmap.values().stream()
                    .flatMap(Collection::stream)
                    .filter(c -> (existingHashmap.values().stream().flatMap(Collection::stream).filter(e->e.getId().equals(c.getId()) && e.getObjectCountry().equals(c.getObjectCountry())))
                            .map(k-> k.setEntityFlag(existingHashmap.values().stream().flatMap(Collection::stream).filter(e->e.getId().equals(k.getId()) && e.getObjectCountry().equals(k.getObjectCountry())).map(r ->r.getEntityFlag()).toString()));
        }
    

this is what i have got so far. but there is an error which i dunno how to correct

any help would be appreciated


Solution

    • Performing a linear scan through existingHashmap for every element in deltaHashmap is extremely wasteful.
    • map is not for performing an action on each element in a Stream. map is for changing the element returned in a Stream. For performing an action, you should use forEach.
    • Calling toString() on a Stream is unlikely to produce useful information.

    I would first map the values of existingHashMap by the properties used for matching. An easy way to implement a compound key is by defining a record class. This mapping by matchable properties allows quicker searching for matches without having to check every value of existingHashmap for every value in deltaHashmap. (Record classes automatically define equals, hashCode, and toString methods based on their members.)

    map should not be used here, because it returns a value—but there is no value to return. You are setting a property in an entity. Doing so does not return anything.

    public void compareTwoHashmaps(
        HashMap<DedupeTableEntity,List<DedupeTableEntity>> deltaHashmap,
        HashMap<DedupeTableEntity,List<DedupeTableEntity>> existingHashmap) {
    
        record Identifiers(String id, String country) {
            static Identifiers of(DedupeTableEntity entity) {
                return new Identifiers(entity.getId(),
                                       entity.getObjectCountry());
            }
        }
    
        Map<Identifiers, DedupeTableEntity> allExisting =
            existingHashmap.values().stream().flatMap(Collection::stream)
                .collect(Collectors.toMap(Identifiers::of, e -> e));
    
        deltaHashmap.values().stream().flatMap(Collection::stream)
            .forEach(delta -> {
                DedupeTableEntity existing =
                    allExisting.get(Identifiers.of(delta));
    
                if (existing != null) {
                    delta.setEntityFlag(existing.getEntityFlag());
                }
            });
    }