我有兩個 Java 物件串列
假設 dataToBeAdded、dataToBeSubtracted
物件具有相同的資料型別并具有多個屬性
DummyObject{ attr1, attr2, attr3, attr4 }
我想合并這些串列,但以有條件的方式如果 attr1、attr2、attr3 在串列中匹配
減去 attr4 并使其成為串列的一部分。
如果屬性不匹配
元素來自 list1(dataToBeadded) 將其按原樣添加到輸出
元素來自 list2(dataToBeSubtracted) 使 attr4 為負數(乘以 -1)
這有點像完全外連接型別的操作
我使用 Maps 和 Streams 做了一些事情
Map<String, DummyObj> dataToBeAddedMap = dataToBeAdded.stream()
.collect(Collectors.toMap(obj -> obj.attr1() obj.attr2() obj.attr3(), item -> item));
Map<String, CumulativeSalesDataByHour> dataToBeSubtractedMap = dataToBeSubtracted.stream()
.collect(Collectors.toMap( obj -> obj.attr1() obj.attr2() obj.attr3(), item ->
new DummyObject(item.attr1(), item.attr2(), item.attr3(), -1 * item.attr4())));
Map<String, DummyObject> resultantData = Stream.of(dataToBeAddedMap, dataToBeSubtractedMap)
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(v1, v2) -> new DummyObject(v1.attr1(),
v1.attr2(),
v1.attr3(),
v1.attr4() v2.attr4())
));
System.out.println(resultantData.values());
這給了我想要的結果,但有沒有更有效的方法來實作這一目標?
編輯1:
添加輸入和預期輸出
DummyObject a1 = new DummyObject("uuid1", "abcd", "mer1", 20D);
DummyObject a2 = new DummyObject("uuid1", "pqrs", "mer1", 25D);
DummyObject a3 = new DummyObject("uuid2", "xyz", "mer1", 18D);
List<DummyObject> dataToBeAdded = ImmutableList.of(a1,a2,a3);
DummyObject d1 = new DummyObject("uuid1", "abcd", "mer1", 5D);
DummyObject d2 = new DummyObject("uuid1", "pqrs", "mer1", 2D);
DummyObject d3 = new DummyObject("uuid3", "xyz", "mer2", 10D);
List<DummyObject> dataToBeSubtracted = ImmutableList.of(d1,d2,d3);
Desired Output
[
DummyObject("uuid1", "abcd", "mer1", 15D); // 20-5
DummyObject("uuid1", "pqrs", "mer1", 23D); // 25-2
DummyObject("uuid2", "xyz", "mer1", 18D);
DummyObject("uuid3", "xyz", "mer1", -10D);
]
uj5u.com熱心網友回復:
如果你真的想要性能,你需要重寫管道——無論發生什么讓你兩個這個問題?這樣做是為了讓您擁有 2 個 Map,使用前 3 個屬性作為鍵(也許創建一個新類來代表這 3 個)。
但是,如果管道不能改變,最快的演算法是:
- 撰寫一個對這些串列進行排序的比較器。
- 制作 2 個迭代器(每個迭代器一個)。
- 制作輸出串列。
- 回圈,為兩個迭代器創建一個“當前項”指標。
- 如果 current-1 低于 current-2(或 current-2 完成),則復制 current-1 并推進 iterator-1。
- 如果 current-2 低于 current-1(或 current-1 完成),翻轉 c-2 上的符號,添加它,然后推進 iterator-2。
- 如果 current-1 和 current-2 相同,則適當更新 attr4,然后將兩者都推進。
- 如果兩者都完成,則回傳輸出串列。
這將是更多的代碼,但它不會產生任何新的瞬態物件,除了 2 個迭代器和一個比較器。
uj5u.com熱心網友回復:
無需為Map要添加的元素和要減去的元素創建兩個額外的元素,您可以立即使用兩者創建一個鏈式流,List并將減去的每個元素映射List到其attr4欄位已被否定的元素。
Map然后,您可以使用collect(Collectors.toMap())終端操作將所有物件收集在一個單一的范圍內。關鍵是前 3 個欄位的串聯,值將是物件本身,而碰撞案例可以通過創建一個新的來處理,DummyObj該欄位與您分組的 3 個欄位相同,第四個欄位attr4由第一個和第二個碰撞值(類似于您在上一個流中所做的)。
另一個小的改進可能是不使用運算子鏈接字串,這為每個連接 創建一個新的,而是使用產生單個的方法來對元素進行分組(更少的開銷)。StringString.format()String
Map<String, DummyObj> mapRes = Stream.concat(dataToBeAdded.stream(), dataToBeSubtracted.stream().map(obj -> {
obj.setAttr4(-1 * obj.getAttr4());
return obj;
}))
.collect(Collectors.toMap(obj -> String.format("%s%s%s", obj.getAttr1(), obj.getAttr2(), obj.getAttr3()),
Function.identity(),
(obj1, obj2) -> new DummyObj(obj1.getAttr1(), obj1.getAttr2(), obj1.getAttr3(), obj1.getAttr4() obj2.getAttr4())
));
這是測驗上述代碼的鏈接:
https://ideone.com/K5qfsI
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/481210.html
上一篇:C#匹配兩個串列并從中創建物件
