Nana
Nana

Reputation: 55

Remove in depth elements using streams

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

Answers (2)

azro
azro

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.

  • You need to iterate over all C elements,
  • You keep the ones that does not correpond (use noneMatch() to check this)
  • for these ones you replace the 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

GhostCat
GhostCat

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

Related Questions