Java 8 Stream API : how to convert a List to a Map<Long, Set> 在列表中有重复的键?

标签 java list dictionary java-8 java-stream

我有一个包含以下字段的类:

public class Item{
   private String name;
   private Long category;
   private Set<Long> containers;
}

我需要做的是转一个

List<Item> items

变成一个

Map<Long/*categoryID*/, Set<Long/*Containers*/>>

使用 Java 8 Stream API。

现在我可以使用 Itarable 得到相同的结果还有一些if ,像这样:

List<Item> items = getItems();
Iterator<Item> itemsIterator = items.iterator();
Map<Long/*categoryID*/, Set<Long/*Containers.ID*/>> containersByCategoryMap = new HashMap<>();

while (itemsIterator.hasNext()) {
    Item item = itemsIterator.next();
    Long category = item.getCategory();
    Set<Long> containers = item.getContainers();

    if (containersByCategoryMap.containsKey(category)) {
        Set<Container> containersByCategory = containersByCategoryMap.get(category);
        containersByCategory.addAll(containers);
    } else {
        Set<Container> containersByCategory = new HashSet<>(containers);
        containersByCategoryMap.put(category, containersByCategory);
    }
}

如何使用 Stream API 获得相同的结果?

我尝试过类似的方法,但显然我遇到了重复键异常,因为每个类别都有多个项目...

containersByCategoryMap = items.stream().collect(Collectors.toMap(item -> item.getCategory(), item -> item.getContainers()));

最佳答案

自 java-9 以来,有 Collectors.flatMapping:

Map<Long, Set<Long>> map = items.stream()
            .collect(Collectors.groupingBy(
                    Item::getCategory,
                    Collectors.flatMapping(x -> x.getContainers().stream(), Collectors.toSet())));

如果没有 java-9,你可以这样做:

Map<Long, Set<Long>> result = items.stream()
            .flatMap(x -> x.getContainers().stream().map(y -> new SimpleEntry<>(x.getCategory(), y)))
            .collect(Collectors.groupingBy(
                    Entry::getKey,
                    Collectors.mapping(Entry::getValue, Collectors.toSet())));

您也可以使用 Map#merge 执行此操作:

    Map<Long, Set<Long>> map2 = new HashMap<>();
    items.forEach(x -> map2.merge(
            x.getCategory(),
            x.getContainers(),
            (left, right) -> {
                left.addAll(right);
                return left;
            }));

关于Java 8 Stream API : how to convert a List to a Map<Long, Set> 在列表中有重复的键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51723042/

相关文章:

java - 如何开启Spring WebFlux的访问日志?

java - 在java中创建json只获取第一个值没有得到所需的格式

Java 我的计时器出了什么问题?

list - Red 语言中的并行列表赋值

dictionary - 结构体作为 Go map 中的键

c# - 使用字典进行重复数据删除的更好方法?

java - 如何使用java api更新elasticsearch中的嵌套字段值

python - 这是用 Python 编写 Luhn 算法的最有效方法吗?

list - 在 Haskell 列表理解中组织元组序列

node.js - redis服务器键值对的值中如何存储一个数组?