簡體   English   中英

從兩個列表中過濾具有相同屬性的對象並更新它們並將其存儲在 Java 8 中的第三個列表中

[英]Filter Objects having the same property from two Lists and Update them and Store it in a 3rd List in Java 8

我有以下 class:

@AllArgsConstructor
@Getter
@Setter
public static class Manipulate {
    private int id;
    private int quantity;
}

我有兩個列表ab

List<Manipulate> a = new ArrayList<>();
a.add(new Manipulate(1,100));
a.add(new Manipulate(2,200));

List<Manipulate> b = new ArrayList<>();
b.add(new Manipulate(1,10));
b.add(new Manipulate(2,20));

我需要根據id屬性過濾這兩個列表。

我想從 a 中包含的對象數量中減去b中包含a對象數量,並將結果存儲到List中。

我的嘗試:

List<Manipulate> c = a.stream().map(k -> {
    b.stream().filter(j -> j.getId() == k.getId())
        .forEach(i -> {
            int i1 = k.getQuantity() - i.getQuantity();
            k.setQuantity(i1);
        });
    return k;
});

我收到以下編譯錯誤:

Required type: List <Manipulate> Provided: Stream<Object>
no instance(s) of type variable(s) R exist so that Stream<R> conforms to List<Manipulate>

您的代碼有幾個問題:

  • map()是一個中間操作,這意味着它不會產生結果值,而是返回另一個 stream。 為了從 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 產生結果,您需要應用終端操作(例如collect()reduce()findFirst() )。 有關詳細信息,請參閱API 文檔

  • 函數式編程中,對傳遞給function的 arguments 進行變異並不是一個好習慣(這就是您在map()中所做的事情)。

  • 您的代碼基於蠻力邏輯(這總是暗示可能的最差性能):對於a中的每個元素,迭代b中的所有元素。 相反,我們可以通過將列表b中存在的所有id放入基於哈希的集合中來索引它們(這將允許在恆定時間內找出特定id是否存在於b中)並將每個id與對應quantity 即我們可以生成HashMap ,將b中的每個id映射到它的quantity

  • 列表ac將是相同的,因為它們將包含相同的引用。 這意味着生成列表c沒有意義的,除非您希望它包含具有列表b中存在的id的元素。

這就是您的代碼可能被重新實現的方式:

List<Manipulate> a = // initializing list a
List<Manipulate> b = // initializing list b

// mapping each `id` in the `b` to it's `quantity`

Map<Integer, Integer> quantityById = b.stream()
    .collect(Collectors.toMap(
        Manipulate::getId,      // keyMapper
        Manipulate::getQuantity // valueMapper
    ));

// generating the list `c`, containing only elements
// with `id` that are present in the `b`
        
List<Manipulate> c = a.stream()
    .filter(m -> quantityById.containsKey(m.getId()))
    .collect(Collectors.toList()); // or .toList() for Java 16+

// updating `quantity` property of each element in `c`
    
for (Manipulate m : c)
    m.setQuantity(
        m.getQuantity() - quantityById.get(m.getId())
    );

如果您不打算更改a中的數據,那么您需要為每個匹配的id創建新的Manipulate實例。 在 stream 中做這件事完全沒問題:

List<Manipulate> a = // initializing list a
List<Manipulate> b = // initializing list b
Map<Integer, Integer> quantityById = // generate a map like shown above

List<Manipulate> c = a.stream()
    .filter(m -> quantityById.containsKey(m.getId()))
    .map(m -> new Manipulate(m.getId(), m.getQuantity() - quantityById.get(m.getId())))
    .collect(Collectors.toList()); // or .toList() for Java 16+

注意:您需要將第三個參數添加到Collectors.toMap()以防列表b中可能存在重復的id

暫無
暫無

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

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