Часто возникает необходимость в преобразовании результатов для запроса типа:
select category, count(*)
from table
group by category
к карте, в которой ключи являются категориями, а значения - количеством записей, относящихся к одной и той же категории.
Многие основы сохранения возвращают результаты такого запроса, как List<Object[]>
, где массивы объектов содержат два элемента (категория и счетчик для каждой строки возвращаемого набора результатов).
Я пытаюсь найти наиболее читаемый способ преобразования этого списка в соответствующую карту.
Конечно, традиционный подход предполагает создание карты и ввод записей вручную:
Map<String, Integer> map = new HashMap<>();
list.stream().forEach(e -> map.put((String) e[0], (Integer) e[1]));
Первый однострочный аппарат, который пришел мне на ум, состоял в том, чтобы использовать доступный Collectors.toMap
коллекционер:
Map<String, Integer> map = list.stream().collect(toMap(e -> (String) e[0], e -> (Integer) e[1]));
Однако я нахожу этот синтаксис e -> (T) e[i]
немного менее читаемым, чем традиционный подход. Чтобы преодолеть это, я мог бы создать метод утилиты, который я могу повторно использовать во всех таких ситуациях:
public static <K, V> Collector<Object[], ?, Map<K, V>> toMap() {
return Collectors.toMap(e -> (K) e[0], e -> (V) e[1]);
}
Тогда у меня есть идеальный однострочный:
Map<String, Integer> map = list.stream().collect(Utils.toMap());
Нет необходимости бросать ключ и значение из-за вывода типа. Однако это немного сложнее понять для других читателей кода (Collector<Object[], ?, Map<K, V>>
в сигнатуре метода утилиты и т.д.).
Мне интересно, есть ли что-нибудь еще в панели инструментов java 8, которая могла бы помочь этому достичь более читаемым/элегантным способом?