Удалить элементы в глубину, используя потоки
У меня есть следующие классы.
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 {}
Что я хочу сделать, это удалить list d
если конкретного поискового запроса нет в списке. Я пытался сделать это, но не повезло. Я думаю, что это удаляет, но ссылка не сохраняется.
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;
});
Кто-нибудь может мне помочь?
2 ответа
То, что вы сделали, создает List<List<D>>
и вы удалите List<D>
элементы, которые не соответствуют, но которые никогда не изменяют объекты, которые у вас есть.
- Вам нужно перебрать все
C
элементы, - Вы оставляете те, которые не соответствуют (используйте
noneMatch()
проверить это) - для этих вы заменяете
list
пустым (или очистить фактическое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());
Поток представляет собой представление "базовой" коллекции. Это означает, что когда вы звоните removeIf()
в потоке "базовая" коллекция вообще не затрагивается.
Вам нужно будет сделать две вещи: сначала вы "соберете" все элементы, которые вы собираетесь удалить, а затем просто удалите их (явным вызовом) из списка, который необходимо изменить:
List<B> toBeDeleted = a.stream()....collect(Collectors.toList());
a.b.removeAll(toBeDeleted);
(вышеприведенное подразумевается как псевдокод, я не запускал его через компилятор)
Как уже говорилось: настоящая проблема здесь - ваше неправильное представление: операции над потоком обычно не влияют на базовую коллекцию.