首页 > 解决方案 > 使用流按多个属性分组和排序:Java 8

问题描述

我有 MainEntity的列表

public class MainEntity {
private String keyword;
private double cost;
private String company;
}

我有CompanyEntity

public class CompanyEntity {
    private double cost;
    private String company;
    }

我正在尝试将我的列表转换为 Map<String,List<CompanyEntity>>关键所在的位置keywordList<CompanyEntity>并将平均所有成本并进行排序。我正在尝试在流和 Java 8 中做到这一点。

对于作为输入的特定关键字,我正在这样做。

List<MainEntity> entityList = keyWordMap.get(entity.getKeyword());
        entityList.add(entity);
        keyWordMap.put(entity.getKeyword(), entityList);

Map<String, Double> average = (keyWordMap.get(keyword)).stream()
            .collect(groupingBy(MainEntity::getCompany,
                    Collectors.averagingDouble(MainEntity::getCtr)));
    result.put(keyword, new ArrayList<>());

    for (Map.Entry<String, Double> entity : average.entrySet()) {
        result.get(keyword).add(new CompanyEntity(entity.getKey(), entity.getValue()));
    }

但我试图为所有关键字创建一个地图。是否有可能或再次迭代整个列表有意义?目前keyowordMapMap<String,MainEntity>我通过迭代列表所做的类型MainEntity,但我想要Map<String,List<MainEntity>>

标签: javacollectionsjava-8java-stream

解决方案


首先,制作一个keyWordMap

Map<String, List<MainEntity>> keyWordMap = 
            mainEntityList
            .stream()
            .collect(Collectors.groupingBy(MainEntity::getKeyword));

然后对map进行迭代,对于每个关键词,可以直接得到CompanyEntity按平均值排序的list,并用map()它来转换数据并收集为List,然后放入result

Map<String,List<CompanyEntity>> result = ....
for (Map.Entry<String, List<MainEntity> entry : keyWordMap.entrySet()) {
    List<CompanyEntity> list = entry.getValue().stream()
                .collect(groupingBy(MainEntity::getCompany,
                        Collectors.averagingDouble(MainEntity::getCtr)))
                .entrySet()
                .stream()
                .sorted(Comparator.comparing(e -> e.getValue()))
                .map(e -> new CompanyEntity(e.getKey(), e.getValue()))
                .collect(Collectors.toList());
    result.put(entry.getKey(), list);
}

或者你想一次性完成

Map<String,List<CompanyEntity>> mapData = 
           mainEntityList
            .stream()
            .collect(Collectors.groupingBy(MainEntity::getKeyWord,
                     Collectors.groupingBy(MainEntity::getCtr,
                        Collectors.averagingDouble(MainEntity::getCtr))))
            .entrySet()
            .stream()
            .collect(Collectors.toMap(m -> m.getKey(),
                 m -> m.entrySet()
                       .stream()
                       .sorted(Comparator.comparing(e -> e.getValue()))
                       .map(e -> new CompanyEntity(e.getKey(), e.getValue()))
                       .collect(Collectors.toList())));

推荐阅读