объединение частичных дубликатов hashmap с новым массивом в java - PullRequest
2 голосов
/ 26 апреля 2019

У меня есть Stream<Map<String, String>>, где каждая карта похожа на отдельную запись и содержит две записи:

  1. Идентификатор автомобиля («ID», «1003»)
  2. Километров ("KMI", "500")

Этот список может содержать карты, которые повторяются таким образом, что 2 или более карт могут иметь одинаковое значение записи идентификатора автомобиля. В основном это: entry1.get ("ID") == entry2.get ("ID"). то, что я хочу сделать, это удалить карты с дублирующимися идентификаторами, а затем также объединить значения KMI вместе. это:

{"ID": "1003", "KMI": "500"}, {"ID": "1003", "KMI": "400"}, { "ID": "1004", "КМИ": "200"}

должно стать таким:

{"ID": "1003", "KMI": "900"}, {"ID": "1004", "KMI": "200"}

Я пытался сделать это только с помощью API потоков, но я не могу обдумать это. Я попытался изменить аналогичный пример, который имел список объектов вот что я получил до сих пор:

List<Map<String, String>> result = new ArrayList<>(
    queryKmAll.collect(
        Collectors.toMap(a1 -> a1.get("ID")), Function.identity(), (Map<String, String> m2, Map<String, String> m1) -> {
            m1.put("KMI", String.valueOf(Double.parseDouble(m1.get("KMI")) + Double.parseDouble(m2.get("KMI"))));

            return m1;
        })
    )
);

Ответы [ 2 ]

2 голосов
/ 26 апреля 2019

Я взял с того места, где ушел ОП.Я немного изменил вашу логику, чтобы вернуть то, что вы хотели.Посмотри на это.Надеюсь, это поможет

Collectors.toMap вернет карту, в которой ключом будет ID и sum of KMI для Function.identity() случаев.Таким образом, возвращение будет Map<Object,Map<String,String>>.Поскольку ожидаемый результат равен Stream<Map<String,String>, я добавил .values().stream().

Stream<Map<String, String>> result = queryKmAll.collect(Collectors.toMap(a1 -> a1.get("ID"),
            Function.identity(), (Map<String, String> m2, Map<String, String> m1) -> {
                m1.put("KMI",
                        String.valueOf(Double.parseDouble(m1.get("KMI")) + Double.parseDouble(m2.get("KMI"))));

                return m1;
            })).values().stream();

result.forEach(System.out::println);
1 голос
/ 26 апреля 2019

То, что вы ищете, это Collectors.groupingBy :

    Map<String, Long> summary = Stream
        .of(
            new HashMap<String, String>() {{
              put("ID", "1003");
              put("KMI", "500");
            }},
            new HashMap<String, String>() {{
              put("ID", "1003");
              put("KMI", "400");
            }},
            new HashMap<String, String>() {{
              put("ID", "1004");
              put("KMI", "200");
            }}
        )
        .collect(Collectors.groupingBy(
            m -> m.get("ID"),
            Collectors.summingLong(m -> Long.valueOf(m.get("KMI")))
        ));

    System.out.println(summary);

Кроме того, вы можете заменить карту классом, скажем Summary:

  public class Summary {

    public Summary(String id, Long kmi) {
      this.id = id;
      this.kmi = kmi;
    }

    private String id;
    private Long kmi;

    public String getId() {
      return id;
    }

    public Long getKmi() {
      return kmi;
    }
  }

А затем используйте:

    Map<String, Long> summary = Stream
        .of(
            new Summary("1003", 500L),
            new Summary("1003", 400L),
            new Summary("1004", 200L)
        )
        .collect(Collectors.groupingBy(
            s -> s.getId(),
            Collectors.summingLong(s -> s.getKmi())
        ));

    System.out.println(summary);

Отпечатки: {1004=200, 1003=900}

...