Как использовать groupingBy, сортировать и уменьшать список объектов в потоках - PullRequest
1 голос
/ 23 января 2020

У меня есть список объектов List<FloatBalance>, который может быть представлен следующим JSON. Я хочу получить наибольшую последнюю запись для каждой валюты в списке и передать сокращенный список обратно на запрос.

    {
        "id": 1,
        "clientId": 50,
        "currency": "GBP",
        "floatType": "ChargeFloat",
        "floatCurrentValue": 300.00,
        "chargeReference": "PROD-1578486576_278",
        "cashOutReference": null,
        "cashInReference": null,
        "targetValue": 3000.00,
        "alertValue": 500.00,
        "maxValue": 4500.00,
        "createdDate": "2020-01-08T12:29:50Z"
    },
...
]

Моя первая попытка - прямая теперь я группирую их по валюте с

Map<String, List<FloatBalance>> result = floats.stream()
                    .collect(groupingBy(FloatBalance::getCurrency));

, а затем группирую их и упорядочиваю по самым последним датам с

Map<String, List<FloatBalance>> floatGrouped = floats.stream()
                    .sorted(Comparator.comparing(FloatBalance::getCreatedDate).reversed())
                    .collect(groupingBy(FloatBalance::getCurrency));

Результат карты

enter image description here

Я также могу сократить список, но мне удалось выполнить эту операцию только в полном списке, который возвращает только самую последнюю запись.

FloatBalance floatGrouped = floats.stream()
                    .sorted(Comparator.comparing(FloatBalance::getCreatedDate))
                    .reduce((first, second) -> second)
                    .orElse(null);

Я ходил кругами, пытаясь это выяснить, я пытался .entrySet() выполнять уменьшение для каждой записи на карте, но компьютер говорит «нет» всему, что я пробовал.

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

Ответы [ 2 ]

3 голосов
/ 23 января 2020
List<FloatBalance> floatBalances = new ArrayList<>(floats.stream()
        .collect(Collectors.toMap(
                FloatBalance::getCurrency,
                Function.identity(),
                BinaryOperator.maxBy(Comparator.comparing(FloatBalance:: getCreatedDate))))
        .values());

Во-первых, получается значение Map, где Key равно currency, а значение floatBalanace. Когда две валюты сталкиваются, происходит слияние, которое разделяет их - или указывает, какую из них выбрать. Это то, что BinaryOperator::maxBy. делает. В основном это говорит: «Я возьму один из двух floatBalancers, где createDate является самым большим». И, в конце, вы просто берете values - что вернет Collection<FloatBalance>.

1 голос
/ 23 января 2020

Вы ищете:

List<FloatBalance> result = floats.stream()
        .collect(Collectors.groupingBy(FloatBalance::getCurrency,
                Collectors.maxBy(Comparator.comparing(FloatBalance::getCreatedDate))))
        .values().stream()
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(Collectors.toList());
...