【问题标题】:Remove in depth elements using streams使用流删除深度元素
【发布时间】:2018-07-12 07:18:48
【问题描述】:

我有以下课程。

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;
        });

有人可以帮我吗?

【问题讨论】:

  • 要明确:你想从流中删除元素,还是从真实列表中删除?!因为后者是不可能的。 a 流上的操作不会改变 a 本身!
  • 来自真实列表。这里真正的列表是“a”,它的类型是 List
  • 所以对象'c'会有一个空列表?如果在它的列表中找到了 searchItem?
  • 是的 Azro,没错。
  • 只是附注,你可以简单地写return ! someExpression;而不是boolean toBeRemoved = true; boolean containsMatch = someExpression; if(containsMatch) { toBeRemoved = false; } return toBeRemoved; 结合这一事实,而不是parameter -&gt; { return expression; },你可以写parameter -&gt; expression...

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


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 几乎是完美的答案,虽然只是一个旁注。 “这意味着当你在流上调用 removeIf() 时”。流没有removeIf 方法,而removeIf 属于Collection 类型的任何东西。 “流上的操作通常不会影响基础集合。”。尽管对于这种特定情况可能是正确的,但流元素并不总是存储在底层集合中,因为有时它们可​​能是按需生成的。
【解决方案2】:

您所做的构建了一个 List&lt;List&lt;D&gt;&gt; 并删除了不对应但永远不会更改您拥有的对象的 List&lt;D&gt; 元素。

  • 您需要遍历所有 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());

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 2019-09-12
    • 2018-03-17
    • 2011-02-28
    • 1970-01-01
    • 2021-08-21
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多