Reputation: 55
I have the following classes.
Class A {
List<B> b
//getters and setters
}
CLass B {
List<C> c
//getters and setters
}
Class C {
List<D> d
//getters and setter
}
Class D {}
What i want to do is remove list d
if a specific search term is not in the list. I have tried to do it but no luck. I think it removes but the reference is not saved.
a.stream()
.flatMap(a-> a.getB().stream())
.flatMap(b-> b.getC().stream())
.map(c-> c.getD())
.collect(Collectors.toList())
.removeIf(list -> {
boolean toBeRemoved = true;
boolean containsMatch = list.stream().anyMatch(w-> {return w.getId().equalsIgnoreCase(searchTerm);});
if(containsMatch) {
toBeRemoved = false;
}
return toBeRemoved;
});
Can someone help me?
Upvotes: 2
Views: 534
Reputation: 54148
What you did builds a List<List<D>>
and you remove List<D>
elements that does not correponds, but that never changes the objects you have.
C
elements,noneMatch()
to check this) list
by an empty one (or clear the actual c.getD().clear()
)
a.stream()
.flatMap(a-> a.getB().stream())
.flatMap(b-> b.getC().stream())
.filter(c -> c.getD().stream().noneMatch(w -> w.getId().equalsIgnoreCase(searchTerm)))
.forEach(c-> c.setD(new ArrayList<>())); // or .forEach(c-> c.getD().clear());
Upvotes: 1
Reputation: 140465
A stream represents a view on the "underlying" collection. This means that when you call removeIf()
on the stream, the "underlying" collection isn't affected at all.
You would need to do two things: first you "collect" all items you intend to delete, and then you simply remove them (in an explicit call) from the list that needs to be changed:
List<B> toBeDeleted = a.stream()....collect(Collectors.toList());
a.b.removeAll(toBeDeleted);
( the above is meant as pseudo code, I didn't run it through the compiler )
As said: the real problem here is your misconception: operations on the stream normally do not affect the underlying collection.
Upvotes: 2