От "Map<String, Collection <String >>" до "Map<String, List <String >>" с использованием Java 8

Есть ли лучший способ преобразовать "Map>" в "Map>"?

Map<String, Collection<String>> collectionsMap = ...
Map<String, List<String>> listsaps =
    collectionsMap.entrySet().stream()
    .collect(Collectors.<Map.Entry<String, Collection<String>>,
        String, List<String>>toMap(
            Map.Entry::getKey,
            e -> e. getValue().stream().collect(Collectors.toList())
        )
    );

Спасибо, что помогаете нам стать лучше

3 ответа

В таких случаях я бы хотел использовать Map.forEach выполнить операцию с использованием побочных эффектов. Потоки по картам несколько громоздки, так как нужно написать дополнительный код для потоковой передачи записей карты, а затем извлечь ключ и значение из каждой записи. В отличие от Map.forEach передает каждый ключ и значение в функцию как отдельный параметр. Вот как это выглядит:

Map<String, Collection<String>> collectionsMap = ...
Map<String, List<String>> listsaps = new HashMap<>(); // pre-size if desired
collectionsMap.forEach((k, v) -> listsaps.put(k, new ArrayList<>(v)));

Если ваша карта большая, вы, вероятно, захотите предварительно изменить размер пункта назначения, чтобы избежать перепрошивки во время его заполнения. Чтобы сделать это правильно, вы должны знать, что HashMap принимает в качестве параметра количество сегментов, а не количество элементов. Это требует деления на коэффициент загрузки по умолчанию 0,75 для правильного предварительного размера с учетом определенного количества элементов:

Map<String, List<String>> listsaps = new HashMap<>((int)(collectionsMap.size() / 0.75 + 1));

1) В Collectors.toMap() вам не нужно повторять универсальные типы, так как они выводятся.

Так:

collect(Collectors.<Map.Entry<String, Collection<String>>,
        String, List<String>>toMap(...)

можно заменить на:

collect(Collectors.toMap(...)

2) Способ преобразования коллекции в Список также может быть упрощен.

Это:

e -> e. getValue().stream().collect(Collectors.toList())

может быть написано как:

e -> new ArrayList<>(e.getValue())

Вы могли бы написать:

Map<String, List<String>> listsaps =
            collectionsMap.entrySet()
            .stream()
            .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    e -> new ArrayList<>(e.getValue())
                )
            );

Я думаю, что это легче читать

Map<String, List<String>> listsaps = new HashMap<>();
collectionsMap.entrySet()
    .stream()
    .forEach(e -> listsaps.put(e.getKey(), new ArrayList<>(e.getValue())));

Если вы просто хотите преобразовать записи в списки, но не хотите менять тип коллекции, вы можете использовать map.replaceAll:

collectionsMap.replaceAll((k, v) -> new ArrayList<>(v));
Другие вопросы по тегам