![](/img/trans.png)
[英]Filter Objects from two lists and do subtract with the attributes and store it in 3rd list in 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;
}
我有兩個列表a
和b
。
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
。
列表a
和c
將是相同的,因為它們將包含相同的引用。 這意味着生成列表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.