使用 java 8 Streams 从 DTO 中的数组列表中删除元素

Removing element from an array list within a DTO using java 8 Streams

我有一个 DTO,它包含几个 ArrayList 类型的属性。

  1. 我想把这个DTO作为参数。
  2. 然后用ArrayList获取属性。
  3. 然后基于一些谓词我想从 ArrayList
  4. 中删除一些元素
  5. 最后return修改后的DTO

    public class SomeDTO{
    
    private String attrOne;
    private String attrTwo;
    private List<SomeOtherDataType> listAttr;
    // getters 
    // setter
    ...
    
    
    }
    
    // This is the method where I want to modify the DTO
    private void modifyDTO(SomeDTO someDTO){
    
     someDTO.getlistAttr()
       .stream()
       /// need help here, how to remove some element from list 
       /// based on some condition.
       /// note the changes in the list should be reflected in DTO 
    
    }
    

    这可以通过简单地执行 forEach 终端操作来完成,但是是否有更好的方法或其他人遵循的任何最佳实践。

谢谢

这里不需要使用流。您可以简单地使用 Collection.removeIf.

来自 javadoc(强调我的)

Removes all of the elements of this collection that satisfy the given predicate. Errors or runtime exceptions thrown during iteration or by the predicate are relayed to the caller.

因此,你可以这样写

someDTO.getlistAttr().removeIf((someOtherDataType) -> /*Your logic here*/)

如果您真的想使用 Streams,那么从您离开的地方,您可以使用 filter 并将通过过滤器的 SomeOtherDataType 元素收集为列表。

List<SomeOtherDataType> filterdList =  someDTO.getlistAttr()
   .stream()
   .filter(someOtherDataType -> /* your logic */)
   .collect(Collectors.toList())

但在此之后,您要么必须

  1. 用上面的filterdList(new SomeDTO(someDTO.getAttrOne(), someDTO.getAttrTwo(), filterdList))1

    创建一个新的SomeDTO
  2. 将现有的listAttr设置为filterdList (someDTO.setListAttr(filterdList))

1 我想你的意思是第二个实例变量的名称是 attrTwo.

其实你有两种方法:

  • 正在收集一个包含要保留的元素的新列表并将其分配给字段

  • 正在从实际列表中删除元素

第二种方式可能是您出于多种原因需要的方式,例如:

  • 通常对于 List 字段,您不想创建新列表来更改其状态。您只想对引用不可变对象的字段这样做。

  • 如果某些对象保留对 List 字段的引用,这些对象将引用旧对象。这是不可取的,并且会产生难以理解的副作用问题。

  • 创建整个筛选对象可能会产生 CPU/memory 的成本,而从现有 List 中删除对象可能效率更高。

1 种方式)重新分配给新对象

 List<SomeOtherDataType> listAttr =
 someDTO.getlistAttr()
        .stream()
        .filter(o -> conditionToKeep)
        .collect(Collectors.toList());
someDTO.setListAttr(listAttr);

2 way) 在当前对象中过滤

someDTO.getlistAttr().removeIf(o -> conditionToRemove);

编辑OP评论

即使过滤掉元素的条件需要挖掘SomeOtherDataType对象和组成它的元素,仍然不需要流。
一个花哨的代码来说明这一点:

someDTO.getlistAttr()
       .removeIf(o -> {
                        Bar bar = o.getFoo().getBar();
                        if (bar != null){
                            List<FooBar> fooBars = bar.getList(); 
                            if (fooBars.contains(...)){
                                 return true; // I remove in this case
                            }
                        }
                        return false; // in any other case I keep
                      }
                );