簡體   English   中英

使用流將 Java 列表轉換為映射,其中映射中的每個值共享相同的屬性

[英]Convert Java list into map where each value in map shares same attribute, using streams

我正在嘗試將列表轉換為映射,以便對於列表元素的某些屬性,映射的鍵是元素 ID,值是具有相同屬性的元素的其他元素 ID。 這使用for循環相當簡單,但我試圖僅使用 Java 流來做到這一點。 主要目標是可讀性,而不是性能。

下面是它在 for 循環中的樣子 - 在這個例子中屬性是colorId

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());
        }
    }
}

這是我對applesWithSameColor理想結果:

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]}

該示例顯示了good輸出。

使用 Java 流執行此操作的好方法是什么? 如果我們也可以避免創建中間地圖applesByColor ,那將是理想的。

您可以從applesByColor Map 流式傳輸值,然后為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)));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM