Группировка потоков по списку типов перечислений - PullRequest
2 голосов
/ 20 октября 2019

У меня есть Класс продукта:

class Product {
    String name;
    List<Group> group;
    //more fields, getters, setters
    public Product(String name, Group... group) {
        this.name = name;
        this.group = Arrays.asList(group);
    }
}

, где Group является перечислением

public enum Group {
    LEISURE,
    SPORT,
    FORMALATTIRE,
    BABY,
    MATERNITY
    //...
}

Из списка продуктов, которые я хочу создать Map<Group,List<Product>>

Пример ввода:

List<Product> productList = new ArrayList<>();

productList.add(new Product("A", Group.BABY, Group.MATERNITY));
productList.add(new Product("B", Group.BABY, Group.LEISURE, Group.SPORT));
productList.add(new Product("C", Group.SPORT, Group.LEISURE));
productList.add(new Product("D", Group.LEISURE, Group.SPORT, Group.FORMALATTIRE));
productList.add(new Product("E", Group.SPORT, Group.LEISURE));
productList.add(new Product("F", Group.FORMALATTIRE, Group.LEISURE));

Если бы группа была одним полем, как имя, которое я мог бы сделать:

productList.stream().collect(Collectors.groupingBy(Product::getName));

Как я могу сделать это с List<Group>?

Ожидаемый результат - что-то вроде ниже, где для каждой группы, которая существует в productList, отображается список товаров, имеющих эту группу в своем поле group

{MATERNITY=[A], FORMALATTIRE=[D, F], LEISURE=[B, C, D, E, F], SPORT=[B, C, D, E], BABY=[A, B]}

Ответы [ 2 ]

2 голосов
/ 20 октября 2019

Вы можете flatMap группа внутри каждого Product до name продукта, а затем сгруппировать ее по Group, сопоставляя соответствующие name s в качестве значения. Например:

Map<Group, List<String>> groupToNameMapping = productList.stream()
        .flatMap(product -> product.getGroup().stream()
                .map(group -> new AbstractMap.SimpleEntry<>(group, product.getName())))
        .collect(Collectors.groupingBy(Map.Entry::getKey,
                Collectors.mapping(Map.Entry::getValue, Collectors.toList())));

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

Map<Group, List<Product>> groupToProductMapping = productList.stream()
        .flatMap(product -> product.getGroup().stream()
                .map(group -> new AbstractMap.SimpleEntry<>(group, product)))
        .collect(Collectors.groupingBy(Map.Entry::getKey,
                Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
2 голосов
/ 20 октября 2019

Вы можете создать поток Entry<Group,String>, используя flatMap, а затем собрать их в Map<Group, List<String>>, используя Collectors.mapping

productList.stream()
               .flatMap(p->p.getGroup()
                            .stream()
                            .map(g->new AbstractMap.SimpleEntry<>(g,p.getName())))   // or from jdk 9 you can use Map.entry(g, p.getName());
               .collect(Collectors.groupingBy(Map.Entry::getKey, 
                       Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
...