Say that we have a 3-dimensional List of Objects:
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
Say that I want to filter "l5" such that if any element in the inner most list is an odd number then the entire list should be deleted, and if that makes the 2nd level list as empty, then that should be deleted in return.
So, for the given example, before filtering if it is:
[[[1,2,4],[2,4,6]], [[1,2,4]]]
After filtering, it should be:
[[[2,4,6]]]
How can I do this using streams in Java?
Since you need your lists to be updated, in the below solution I am using removeIf
method of the List
to remove any elements which does not meet the necessary criteria. So for removeIf
to work, the list should not be immutable. So replace the var list = List.of(...)
code with var list = new ArrayList<>(List.of(...));
(Note: Null checks have been ignored as well.)
Now, this problem could be split into components:
Predicate<OneDObject> hasOdd = obj-> obj.getList().stream().anyMatch(i -> i % 2 != 0);
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