Как сделать множественную агрегацию в списке HashMaps с Java 8 - PullRequest
0 голосов
/ 15 октября 2018

У меня проблема с реализацией java 8, касающаяся множественного агрегирования списка HashMap (желательно с функцией "reduce", но не обязательно)

Мне нужно выполнить множественное агрегирование по имени ключа - "service" with split("_")[0] какв Json ниже:

Предположим, моя структура данных:

 List<Map<String, Object>> payments = new ArrayList<>();
  for(int i=0 ; ....i++){
      Map<String, String> map = new HashMap<>();
      map.put("service","IMAP_"+i);
      map.put("storageValue",<some value>)
      ....
      payments.add(map);
  }

Json:

{
  "payments": [
    {
      "service": "IMAP_1",
      "storageValue": 10,
      "users": "10"
    },
    {
      "service": IMAP_2,
      "storageValue": 20,
      "users": "1"
    },
    {
      "storageValue": 200,
      "service": "Office 365 Exchange_1",
      "users": "15"
    },
    {
      "storageValue": 200,
      "service": "Office 365 Exchange_2",
      "users": "10"
    },
    {
      "storageValue": 50,
      "service": "SalesForce_1",
      "users": "100"
    }
  ]
}

Результат должен быть:

{
      "payments": [
        {
          "service": "IMAP",
          "storageValue": 30,
          "users": "11"
        },
        {
          "storageValue": 400,
          "service": "Office 365 Exchange",
          "users": "25"
        },
        {
          "storageValue": 50,
          "service": "SalesForce",
          "users": "100"
        }
      ]
    }

должно быть что-то ..

payments.stream().forEach(paymet -> {
                paymet.entrySet().stream().map(....?...).reduce()...
            );

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Попробуйте это.это не элегантность:).

сначала измените значение ключа service на новое значение

 payments.stream()
            .forEach(item -> item.put("service", item.get("service").split("_")[0]));

, затем

HashMap<String, HashMap> mapOfMaps = payments.stream()
            .collect(Collectors.toMap(hashMap -> hashMap.get("service"),
                    hashMap -> (HashMap) hashMap,
                    YOURCLASS::merge, HashMap::new));
List<HashMap> result = new ArrayList<>(mapOfMaps.values());

и определите метод объединениядве карты вроде:

private static HashMap<String, String> merge(HashMap<String, String> map1, HashMap<String, String> map2) {
    if (map1.get("service").equals(map2.get("service"))) {
        Long storageValue = Long.valueOf(map1.get("storageValue")) + Long.valueOf(map2.get("storageValue"));
        map1.put("storageValue", storageValue.toString());
        Long users = Long.valueOf(map1.get("users")) + Long.valueOf(map2.get("users"));
        map1.put("users", users.toString());
    }
    return map1;
}
0 голосов
/ 15 октября 2018

Вот неполное предложение, которое объединяет Collectors.groupingBy с Collectors.reducing.

Map<String,Optional<Map<String,Object>>> result = 
    payments.stream ().collect(Collectors.groupingBy (map -> map.get ("service").split ("_")[0],
                               Collectors.reducing ((m1,m2)-> {
                                   Map<String,String> m = new HashMap<>();
                                   m.put("service",m1.get("service")); // you may have to remove the _1 suffix
                                   m.put("storageValue",(Integer)m1.get("storageValue")+(Integer)m2.get("storageValue"));
                                   m.put("users",(Integer)m1.get("users")+(Integer)m2.get("users"));
                                   return m;
                               })));

Обратите внимание, что, поскольку ваши Map s содержат значения String, добавлять их значения немного неудобноMap как будто они числа.Вам придется выполнить некоторые преобразования из String в int и наоборот.

Может быть полезно преобразовать каждый Map в экземпляр некоторого класса, имеющего свойства storage, users и storageValue.Тогда у вас может быть метод, который объединяет два таких экземпляра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...