Группирование потоковBy: сокращение до первого элемента списка

У меня есть List<Valuta>, который может быть представлен (упрощен) JSON-стиле:

[{codice = EUR, description = Euro, ratio = 1}, {codice = USD, description = Dollars, ratio = 1.1}]

Я хочу преобразовать это в Map<String, Valuta> следующим образом:

{EUR = {codice = EUR, description = Euro, ratio = 1}, USD = {codice = USD, description = Dollars, ratio = 1.1}}

Я написал этот однострочный шрифт:

getValute().stream().collect(Collectors.groupingBy(Valuta::getCodice));

но это возвращает Map<String, List<Valuta>> вместо того, что мне нужно.

Я полагаю, что функция mapping() будет работать для меня, но не знаю, как это сделать.

Ответы

Ответ 1

На самом деле вам нужно использовать Collectors.toMap здесь вместо Collectors.groupingBy:

Map<String, Valuta> map = 
    getValute().stream()
               .collect(Collectors.toMap(Valuta::getCodice, Function.identity()));

groupingBy используется для группировки элементов потока на основе функции группировки. 2 Потоковые элементы, которые будут иметь одинаковый результат с функцией группировки, будут по умолчанию собраны в List.

toMap будет собирать элементы в Map, где ключ является результатом применения заданного ключа, а значение - результат применения преобразователя значений. Обратите внимание, что toMap, по умолчанию, генерирует исключение, если встречается дубликат.

Ответ 2

Вы можете использовать Collectors.toMap(keyMappingFunction, valueMappingFunction)

Map<String, Valuta> map = list
        .stream()
        .collect(Collectors.toMap(Valuta::getCodice, v -> v));

Вы можете заменить v->v на Function.identity(), если вы найдете его более читаемым.

Ответ 3

Немного поздно в игре, но попробуйте следующее:

Map<String, Valuta> map = 
    getValute().stream()
               .collect(Collectors.groupingBy(Valuta::getCodice,
                            Collectors.collectingAndThen(
                                Collectors.toList(), 
                                values -> values.get(0))));