假設我們有一個 3 維的物件串列。
class OneDObject {
int id;
List<Integer> list;
OneDObject(int id, List<Integer>list) { // Constructor }
// Getters and Setters
}
class TwoDObject {
int id;
List<OneDObject> list;
TwoDObject(int id, List<OneDObject> list) { // Constructor }
// Getters and Setters
}
var l1 = List.of(1,2,4);
var l2 = List.of(2,4,6);
var obj1d1 = new OneDObject(1, l1);
var obj1d2 = new OneDObject(2, l2);
var l3 = List.of(obj1d1, obj1d2);
var l4 = List.of(obj1d1);
var obj2d1 = new TwoDObject(3, l3);
var obj2d2 = new TwoDObject(4, l4);
var l5 = List.of(obj2d1, obj2d2); // 3-d list
假設我想過濾“l5”,如果最內層串列中的任何元素是奇數,則應洗掉整個串列,如果這使第二級串列為空,則應將其洗掉作為回報。
因此,對于給定的示例,在過濾之前是否為:
[[[1,2,4],[2,4,6]], [[1,2,4]]]
過濾后應該是:
[[[2,4,6]]]
如何在 Java 中使用 Streams 來做到這一點?
uj5u.com熱心網友回復:
由于您需要更新串列,因此在下面的解決方案中,我使用removeIf的方法List來洗掉任何不符合必要條件的元素。所以為了removeIf作業,串列不應該是不可變的。所以將var list = List.of(...)代碼替換為var list = new ArrayList<>(List.of(...));
(注意:空檢查也被忽略了。)
現在,這個問題可以分成幾個部分:
- 用于識別串列是否有任何奇數元素的謂詞。
Predicate<OneDObject> hasOdd = obj-> obj.getList().stream().anyMatch(i -> i % 2 != 0);
- 謂詞從 2d 串列中洗掉物件,該串列在其 1d 串列中有奇數元素。
Predicate<TwoDObject> validate2d = obj -> {
// remove any 1d list that has atleast one odd number.
obj.getList().removeIf(hasOdd);
// check if there are any valid 1d lists
return obj.getList().isEmpty();
};
- 現在將謂詞應用于最終串列:
l5.removeIf(validate2d); // l5 will now contain only the 2d object having [2,4,6] list
uj5u.com熱心網友回復:
這是最終代碼(在 Java 中,但我認為它應該幾乎可以與 Kotlin 互換)
List<TwoDObject> l6 = l5.stream()
.peek(twoDObject -> {
List<OneDObject> filteredOneDObjectList = twoDObject.getList()
.stream()
.filter(oneDObject -> oneDObject.getList()
.stream()
.noneMatch(i -> i % 2 == 1))
.toList();
twoDObject.setList(filteredOneDObjectList);
})
.filter(twoDObject -> twoDObject.getList().size() > 0)
.toList();
首先我們通過twoDObject呼叫來遍歷每一個Stream#peek,然后流式傳輸它的串列并過濾掉每個包含奇數的oneDObject。然后將串列保存回當前的 twoDObject。
最后我們過濾掉所有空的twoDObjects。
請注意,它Stream#peek通常僅用于除錯目的,而不是改變流元素。
在這種情況下,它也可以替換為
List<TwoDObject> l6 = l5.stream()
.map(twoDObject -> {
...
return twoDObject;
})
...
uj5u.com熱心網友回復:
為了實作您正在尋找的東西,我們需要將流操作和集合方法與功能介面一起使用。
在下面的代碼中,首先我們使用 peek 聚合操作來檢查每個 TwoDbObj 實體。
然后,對于它們中的每一個,我們檢查它們的 OneDbObj 串列并洗掉至少包含奇數的實體。
一旦 OneDbObj 串列被最里面的 Integer 串列過濾,我們只保留串列至少包含一個值的 TwoDbObj 實體(它也可以寫為 !isEmpty)。
public class Main {
public static void main(String[] args) {
List<TwoDObject> l5 = new ArrayList<>(List.of(
new TwoDObject(3, new ArrayList<>(List.of(
new OneDObject(1, new ArrayList<>(List.of(1, 2, 4))),
new OneDObject(2, new ArrayList<>(List.of(2, 4, 6)))))),
new TwoDObject(4, new ArrayList<>(List.of(new OneDObject(1, new ArrayList<>(List.of(1, 2, 4))))))));
System.out.println(l5);
List<TwoDObject> listFiltered = l5.stream()
.peek(twoObj -> twoObj.getList().removeIf(oneObj -> oneObj.getList().stream().anyMatch(i -> i % 2 != 0))) //For each TwoDbObj we get rid of the OneDbObj list whose elements contain at least an odd number
.filter(twoObj -> twoObj.getList().size() > 0) //Keeping only the TwoDbObj instances whose list contains any element
.collect(Collectors.toList());
System.out.println(listFiltered);
}
}
在這里,我將粘貼您的示例類的部分實作,以模擬我執行的測驗。
class OneDObject {
int id;
List<Integer> list;
OneDObject(int id, List<Integer> list) {
this.id = id;
this.list = list;
}
public List<Integer> getList() {
return list;
}
public String toString() {
return String.format("%s", list);
}
}
class TwoDObject {
int id;
List<OneDObject> list;
TwoDObject(int id, List<OneDObject> list) {
this.id = id;
this.list = list;
}
public List<OneDObject> getList() {
return list;
}
public String toString() {
return String.format("%s", list);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/463835.html
