Один элемент в нескольких группах при группировке с потоковым API - PullRequest
2 голосов
/ 10 апреля 2019

Я проверяю какой-то старый код, где я группирую элементы.Это выглядит примерно так:

Map<Long,List<Items>> groupedItems = ...
for (long groupid : groups){
    for (Item item :items){
        if (isGroupAccepting(item.getId(),groupid) || groupid == item.getGroup()) {
            groupedItems.get(groupid).add(item);
        }
    }
}

Я планировал заменить его с помощью группировки из потокового API, но я застрял.Это хорошо работает для моего второго условия, но как поступить с первым, когда элемент должен быть добавлен в каждую группу, которая принимает этот тип элемента?Это действительно возможно, или я борюсь здесь без дела?

Ответы [ 2 ]

5 голосов
/ 10 апреля 2019

Вы можете создать пары всех допустимых идентификаторов групп и элементов, а затем сгруппировать их по идентификатору группы:

Map<Long,List<Item>> groupedItems =
    groups.stream()
          .flatMap(g -> items.stream()
                             .filter(i -> isGroupAccepting(i.getId(),g) || g == i.getGroup())
                             .map(i -> new SimpleEnty<>(g,i))
          .collect(Collectors.groupingBy(Map.Entry::getKey,
                   Collectors.mapping(Map.Entry::getValue,
                                      Collectors.toList())));
1 голос
/ 10 апреля 2019

Попробуйте Collectors.flatMapping, если вы используете Idk 9 или выше:

// import static java.util.stream.Collectors.*;
Map<Long, List<Item>> groupedItems = groups.stream()
    .collect(groupingBy(Function.identity(),
        flatMapping(
            groupId -> items.stream()
                .filter(item -> isGroupAccepting(item.getId(), groupId) || groupId == item.getGroup()),
            toList())));

Не уверен, почему вы хотите попробовать заменить цикл for на lambdas / Stream API.Для меня код for выглядит великолепно.В большинстве случаев лямбда-код выглядит некрасиво и труднее для понимания.

...