当前位置: 首页 > 知识库问答 >
问题:

使用流将Java列表转换为map,其中map中的每个值共享相同的属性

曾嘉福
2023-03-14

我试图将list转换成一个map,这样对于list元素的某个属性,map的键是元素ID,而值是具有相同属性的元素的其他元素ID。使用for循环非常简单,但我尝试使用专门的Java流来实现。主要目标是可读性,而不是性能。

class Apple {
    int _appleId; // different for each apple
    int _colorId; // same for some apples

    Apple(int appleId, int colorId) {
        _appleId = appleId;
        _colorId = colorId;
    }

    int getAppleId() { return _appleId; }
    int getColorId() { return _colorId; }
}

public static void main(String[] args) {
    Apple apple1 = new Apple(1, 7);
    Apple apple2 = new Apple(2, 7);
    Apple apple3 = new Apple(3, 7);
    Apple apple4 = new Apple(4, 8);
    Apple apple5 = new Apple(5, 8);
    Apple apple6 = new Apple(6, 9);

    List<Apple> apples = List.of(apple1, apple2, apple3, apple4,
        apple5, apple6);

    // applesByColor: {7=[1, 2, 3], 8=[4, 5], 9=[6]}
    Map<Integer, Set<Integer>> applesByColor = apples.stream().collect(
        Collectors.groupingBy(Apple::getColorId,
            Collectors.mapping(Apple::getAppleId, Collectors.toSet())));

    // applesWithSameColor:
    // {1=[1, 2, 3], 2=[1, 2, 3], 3=[1, 2, 3], 4=[4, 5], 5=[4, 5], 6=[6]}
    Map<Integer, Set<Integer>> applesWithSameColor = new HashMap<>();
    for (var entry : applesByColor.entrySet()) {
        for (var appleId : entry.getValue()) {
            applesWithSameColor
                .computeIfAbsent(appleId, k -> new HashSet<>())
                .addAll(entry.getValue());
        }
    }
}
best:   {1=[2, 3], 2=[1, 3], 3=[1, 2], 4=[5], 5=[4]}
better: {1=[2, 3], 2=[1, 3], 3=[1, 2], 4=[5], 5=[4], 6=[]}
good:   {1=[1, 2, 3], 2=[1, 2, 3], 3=[1, 2, 3], 4=[4, 5], 5=[4, 5], 6=[6]}

共有1个答案

夏侯宏旷
2023-03-14

您可以只从AppleSbyColorMap中对值进行流式处理,然后在Set中为每个值创建条目,然后将它们收集到Map

Map<Integer, Set<Integer>> applesWithSameColor = applesByColor.values().stream()
            .flatMap(set -> set.stream().map(val -> Map.entry(val, set)))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

在重复键的情况下,也可以使用合并功能,以避免冲突

collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) ->v1)));
 类似资料:
  • 我想用Java8Stream API将一个Java POJO列表转换为一个非静态方法中的映射。 我的折线图需要x轴的日期字符串值列表和Y轴的数值列表。这是一种典型的地图格式。但我的数据库为我返回了一个POJO列表。我不喜欢在没有Java8流API的帮助下进行循环。我尝试了这个[ask}(Java 8 List of Objects to map of values)中的方法。但是,我面临两个问题。

  • 我尝试了这种方法,但得到了强制转换异常,不能将字符串转换为整数。

  • 我有一个标签类,它包含一个项目列表 我有一个标签列表,其中每个标签都有一个项目列表 我想把它转换成一个映射,其中的项目是key,而tagName是值。 预期产出: 我尝试了Stream/FaltMap/GroupingBy的各种组合,但没有得到预期的输出。你能帮帮我吗。谢谢

  • 我收到编译器错误无法解析方法“get key()”

  • 我有一个映射,它包含日期作为键和(另一个字符串作为键和列表作为值的映射)作为值。,我想填充另一个将String作为键和double作为值的映射。FlexiServer的内容包括 因此,基本上,我想首先迭代外部映射以获得内部映射,然后迭代内部映射以获得FlexiServers列表,并填充新的映射,其中服务器号作为键,数量列表作为值。我如何使用Java8流来实现这一点呢? 我尝试使用for循环,但我希

  • 问题内容: 我从“ reflect”包中的函数调用获取此返回值: 。 想知道我是否可以在返回值内访问实际地图,如果可以,怎么办? 编辑: 因此,这是我在进行返回Value对象的调用的地方。它返回`[< map[string]string Value ][< map[string]string Value >]`为常规地图。 问题答案: 使用方法可以将大多数反射对象转换回一个值。 获取此值后,可以将