使用流删除深层元素

时间:2018-07-12 07:18:49

标签: java java-8 java-stream remove-if

我有以下课程。

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 个答案:

答案 0 :(得分:2)

流表示“基础”集合的视图。这意味着当您在流中调用removeIf() 时,“底层”集合根本不受影响。

您需要做两件事:首先,您“收集”您打算删除的所有项目,然后只需从显式调用中将它们删除(在显式调用中):

List<B> toBeDeleted = a.stream()....collect(Collectors.toList());
a.b.removeAll(toBeDeleted);

(以上是伪代码,我没有通过编译器运行)

如前所述:真正的问题是您的误解:流上的操作通常不会不会影响基础集合。

答案 1 :(得分:1)

您所做的工作将建立一个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());