Say that we have a 3-dimension List of Objects.
class Custom {
int id;
List<String> list;
Custom(id, list) { // Constructor }
// Getters and Setters
}
class CustomContainer {
int id;
List<Custom> list;
CustomContainer(id, list) { // Constructor }
// Getters and Setters
}
var l1 = List.of("abc", "def", "acd");
var l2 = List.of("bed", "fed", "aed");
var c1 = new Custom(1, l1);
var c2 = new Custom(2, l2);
var l3 = List.of(c1, c2);
var l4 = List.of(c2);
var cc1 = new CustomContainer(3, l3)
var cc2 = new CustomContainer(4, l4)
var containers = List.of(cc1, cc2);
Say that I want to filter "containers" such that, I want to remove all elements from the inner most list that starts with "a". So, the output should be (considering that the toString() prints only the Strings in the list):
[[["def"],["bed", "fed"]], [["bed", "fed"]]]
How can I get this using Streams in Java?
CodePudding user response:
Since you need to work on the innermost collection but you want to collect the outermost elements, you need to process the List
of CustomContainer
and then for each element's list invoke the foreach
(collection method not stream method) and removeIf
.
List<CustomContainer> res = containers.stream()
.peek(container -> container.getList().forEach(custom -> custom.getList().removeIf(str -> str.startsWith("a"))))
.collect(Collectors.toList());
While testing your code, I've also noticed that those sublists have been created with List.of
which returns and immutable list, any attempt of modifying such type of collections will throw an UnsupportedException. You might want to write them like this if they correspond to your actual code:
var l1 = new ArrayList(List.of("abc", "def", "acd")); //Conversion constructor
var l2 = new ArrayList(List.of("bed", "fed", "aed")); //Conversion constructor
var c1 = new Custom(1, l1);
var c2 = new Custom(2, l2);
var l3 = new ArrayList(List.of(c1, c2)); //Conversion constructor
var l4 = new ArrayList(List.of(c2)); //Conversion constructor
var cc1 = new CustomContainer(3, l3);
var cc2 = new CustomContainer(4, l4);
var containers = new ArrayList<>(List.of(cc1, cc2)); //Conversion constructor
By using the conversion constructor, you're basically adding in a bulk operation all the elements from the immutable list
to your mutable ArrayList
.