Iterate Array of Map<String,Object> and return Map<Long,Long> using Java 8

Viewed 1203

I have an Array of Map. In which I need to do some calculation and return Another Map with the addition of the same key count into the value in the result. I have tried the below one. But as it's running parallel, it does not add it.

Please help to improve it

I can able to achieve this in a normal for loop.

public Map<Long,Long> solve(Map<String,Stats>... map){
        Map<Long,Long> resultCount = new HashMap<Long,Long>();
        if(map != null){
       
            resultCount = Arrays.stream(map).filter(Objects::nonNull).map(map -> getUserCountMap(map))
            .collect(HashMap::new, Map::putAll, Map::putAll);
  
    }
        return resultCount;
    }
    
   public Map<Long,Long>  getUserCountMap(Map<String, Stats> map) {
       Map<Long,Long> resultCount = new HashMap<Long,Long>();
       
       map.forEach((k,v)->{
           try {
                
               String key = (String) k;
               Stats userValue = (Stats) v;
               Long userId = new Long(key);
               System.out.println("key :::"+key+":::"+resultCount.getOrDefault(userId, 0l));
               Optional<Long> count = userValue.getCount();
               System.out.println(count.get());
               count.ifPresent(aLong -> resultCount.put(userId, (resultCount.getOrDefault(userId, 0l) + aLong)));
               System.out.println(resultCount);

           } catch (Exception e) {
           } 
       }
       );
       
       System.out.println("ret "+resultCount);
           return resultCount;
       
   }

Any good document to understand Java 8 Streams API and various intermediate and terminal operations

1 Answers

You are not using the correct collector.

You can use Collectors.toMap with a merge function that would add the values of the same key.

But first I suggest you transform your Stream<Map<>> to a Stream<Map.Entry<>> of all the entries of all the Maps.

  resultCount = 
      Arrays.stream(map)
            .filter(Objects::nonNull)
            .flatMap(map -> getUserCountMap(map).entrySet().stream())
            .collect(Collectors.toMap(Map.Entry::getKey,
                                      Map.Entry::getValue,
                                      (v1,v2)->v1+v2));

An attempt to get rid of getUserCountMap:

  resultCount = 
      Arrays.stream(map)
            .filter(Objects::nonNull)
            .flatMap(map -> map.entrySet().stream())
            .map(e -> new SimpleEntry<Long,Long>(Long.valueOf(e.getKey()),e.getValue().getCount().orElse(0L)))
            .collect(Collectors.toMap(Map.Entry::getKey,
                                      Map.Entry::getValue,
                                      (v1,v2)->v1+v2));

I'm not sure the latter is completely equivalent to your getUserCountMap logic.

Related