Частично сгладить вложенные коллекции в Java с помощью Lambdas - PullRequest
2 голосов
/ 06 июня 2019

У меня есть вложенная коллекция как таковая

Map<Integer, Map<Integer, List<Integer>>> nodes = new TreeMap<>()

Мне нужно преобразовать внутреннюю карту в List<List<Integer>>.Порядок внутреннего списка должен быть сохранен.По сути, для каждой записи на внешней карте, итерируйте по внутренней карте, добавьте список как есть в список списков.

Я могу сделать это по старинке.

    List<List<Integer>> result = new ArrayList<>();
    for(Map.Entry<Integer, TreeMap<Integer, List<Integer>>> entry : nodes.entrySet()) {
        Map<Integer, List<Integer>> outer = entry.getValue();
        ArrayList<Integer> tmp = new ArrayList<>();
        for (Map.Entry<Integer, List<Integer>> inner : outer.entrySet()) {
            tmp.addAll(inner.getValue());
        }
        result.add(tmp);
    }

Как это сделать с лямбдами?Это не работает

nodes.entrySet().stream().flatMap(e -> e.getValue().entrySet().stream()).map(e2 -> result.add(e2.getValue()))

Ответы [ 2 ]

2 голосов
/ 06 июня 2019

Как это сделать с лямбдами? Это не работает

Здесь вы никогда не вызываете операцию завершения, поэтому поток никогда не используется. :

nodes.entrySet().stream().flatMap(e -> e.getValue().entrySet().stream()).map(e2 -> result.add(e2.getValue()))

Добавьте любую терминальную операцию, например count(), и вы увидите работающий поток.
Не забывайте, что потоки ленивы, и поэтому вычисления эффективно выполняются только тогда, когда вызывается операция терминала.

Таким образом, вы догадываетесь, что ваш путь не является правильным способом сделать что-то с Stream.
Вам не нужно использовать List как переменную, которую вы будете заполнять в потоке. Потоки предназначены для сбора по мере того, как они производят результат, и сбор в List, наконец, является терминальной операцией, которая пропущена в вашем исходном коде.

Кроме того, в качестве дополнительного примечания вы должны просто передавать значения каждого уровня карты вместо записей, поскольку вы никогда не используете ключи.
Вот код для каждого шага фактического типа возврата:

List<List<Integer>> result =
        nodes.values() // Collection<Map<Integer, List<Integer>>>
             .stream() // Stream<Map<Integer, List<Integer>>> 
             .flatMap(m -> m.values() // Collection<List<Integer>>> 
                           .stream()) // Stream<List<Integer>>> 
             // flatMap() prevents Stream<Stream<...>>. 
             // Indeed we get just Stream<List...>>
             .collect(Collectors.toList());
1 голос
/ 06 июня 2019

Этот должен сделать трюк:

Map<Integer, Map<Integer, List<Integer>>> nodes = new TreeMap<>();
List<List<Integer>> list = nodes.values()
    .stream()
    .flatMap( map -> map.values().stream() )
    .collect( Collectors.toList() );

Пояснение: Сначала вы получаете поток карт с карты, используя:

nodes.values().stream()

затем вы сглаживаете эти карты с помощью:

.flatMap( map -> map.values().stream() )

И наконец соберите их с помощью:

.collect( Collectors.toList() )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...