Преобразование List в Map>
Нужно преобразовать список из слов в мэп, где ключем является первая буква слова, значением - список слов, начинающихся на указанную букву, с использованием потоков Stream API.
Пока удалось собрать только мэп, где в значениях лежит только список из одного слова, как собрать список из нескольких слов не могу понять.
List<String> wordsList = Arrays.asList(words);
Map<Character, List<String>> initialMap = wordsList.stream()
.collect(Collectors.toMap(
e -> e.charAt(0)
,t -> Collections.singletonList(t)
,(e1, e2) -> e1
));
Прошу помочь, хотя бы в какую сторону думать.
Ответы (1 шт):
Как было отмечено в комментарии, в простейшем случае достаточно использовать Collectors.groupingBy
.
Также нет необходимости строить список wordList
из массива слов words
, чтобы получить стрим строк, достаточно использовать Stream.of
или Arrays.stream
:
Map<Character, List<String>> initialMap = Arrays.stream(words)
.collect(Collectors.groupingBy(e -> e.charAt(0)));
Для получения мапы, отсортированной по ключам, можно использовать такую разновидность коллектора groupingBy
:
SortedMap<Character, List<String>> sortedMap = Stream.of(words)
.collect(Collectors.groupingBy(
e -> Character.toLowerCase(e.charAt(0)),
TreeMap::new,
Collectors.toList()
));
Ещё один вариант может использовать метод forEach
, который унаследован в списке из интерфейса Iterable
Iterable::forEach
, и в стриме Stream::forEach
.
При этом результирующая мапа будет создаваться заранее и заполняться при помощи метода Map::computeIfAbsent
, чтобы создавать значения в мапе (пустые списки):
Map<Character, List<String>> map = new HashMap<>(); // или любой нужный тип
Arrays.stream(words)
// Arrays.asList(words) // допустимый вариант
.forEach(s -> map.computeIfAbsent(s.charAt(0), k -> new ArrayList<>())
.add(s) // List::add - добавили элемент
);