Сгруппируйте список данных карты во вложенный HashMap в Java - PullRequest
0 голосов
/ 21 марта 2019

Ввод: у меня есть список карт (ключ - значение пары) и группировка ключей

Например, List<Map<String,String>> inputData JSON

[
 {
    'a': 'German',
    'b': 'Audi',
    'e': 'T3'
 },
 {
    'a': 'German',
    'b': 'BMW',
    'c': 'T6'
 },
 {
    'a': 'American',
    'b': 'Tesla',
    'c': 'T6'
 }
]

и groupingKeys = a and b

Для ключа группировки a -> я создам два сегмента, один для немецкого и другого американского, и в каждом блоке я снова создаю сегмент для значения b, проверьте следующее

Я хочу произвести следующее: Map<String, Map<String, List<Map>> - вложенность карт == количество ключей группировки, здесь это 2

{
   German: {
       Audi: [
            {
               'a': 'German',
               'b': 'Audi',
               'e': 'T3'
            }
       ],
       BMW: [
            {
               'a': 'German',
               'b': 'BMW',
               'c': 'T6'
            }
       ]
   },
   American: {
      Tesla: [
          {
            'a': 'American',
            'b': 'Tesla',
            'c': 'T6'
          }
      ]
   }
}

То, что я пытался:

inputData.stream().collect(Collectors.groupingBy(mapItem -> this.constructGroupingKey(groupingKeys, mapItem)));

//constructGroupingKey - this joins the values of of given grouping keys

Таким образом, я могу создать составной ключ, например, German-Audi или German-BMW и сохранить соответствующий элемент, но это не то, что я хочу точно.

Как @Naman сказал здесь о конкретном классе - следующий делает его одним вкладышем, но я не могу делать предположения о данных, это тип Map

Map<String, Map<String, List<ConcreteClass>>> output = inputData.stream().collect(Collectors.groupingBy(ConcreteClass::getCountry, Collectors.groupingBy(ConcreteClass::getCarType)));

Буду признателен за другие идеи, спасибо. Мне также любопытно, могу ли я получить группировку на основе данных без указания ключей группировки.

Ввод имеет динамический характер, ключ и значение определяются вводом

Ответы [ 2 ]

1 голос
/ 21 марта 2019

Просто дважды щелкните на представлении ввода в качестве конкретного класса.Это выглядело бы намного проще и понятнее:

Map<String, Map<String, List<ThrowAway>>> multipleGrouping(List<ThrowAway> inputData) {
    return inputData.stream()
            .collect(Collectors.groupingBy(ThrowAway::getA,
                    Collectors.groupingBy(ThrowAway::getB)));
}

, где я только что создал образец класса, такой же, как ваше представление карты:

class ThrowAway {
    String a;
    String b;
    String c;

    String getA() {
        return a;
    }

    String getB() {
        return b;
    }
}
0 голосов
/ 24 марта 2019

Поскольку вы ищете динамическое решение, вот другой подход:

Вы можете использовать следующий метод группировки, чтобы передать два ключа для:

public Map<String, Map<String, List<Map<String, String>>>> group(List<Map<String, String>> list, String key1, String key2) {
    return list.stream().collect(
            Collectors.groupingBy(m -> m.get(key1),
                    Collectors.groupingBy(m -> m.get(key2))
            )
    );
}

Проблема здесь заключается в том, еслиключ не существует на карте, которую вы получаете NullPointerException.Чтобы предотвратить это, вы можете использовать map.getOrDefault() с ключом по умолчанию:

public Map<String, Map<String, List<Map<String, String>>>> group(List<Map<String, String>> list, String key1, String key2, String noneKey) {
    return list.stream().collect(
            Collectors.groupingBy(m -> m.getOrDefault(key1, noneKey),
                    Collectors.groupingBy(m -> m.getOrDefault(key2, noneKey))
            )
    );
}

Вызовите один из методов со следующими параметрами:

Map<String, Map<String, List<Map<String, String>>>> result = group(list, "a", "b");

или

Map<String, Map<String, List<Map<String, String>>>> result = group(list, "a", "b", "none");
...