使用Java 8流从DTO的数组列表中删除元素

时间:2018-08-04 06:25:18

标签: java java-8 java-stream dto mutable

我有DTO,其中包含多个类型为ArrayList的属性。

  1. 我要将此DTO作为参数。
  2. 然后使用ArrayList获取属性。
  3. 然后基于一些谓词,我想从ArrayList
  4. 中删除一些元素
  5. 最后返回修改后的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终端操作来完成,但是有没有更好的方法可以做到这一点或其他人遵循的最佳实践呢?

谢谢

2 个答案:

答案 0 :(得分:4)

实际上,您有两种方法:

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

  • 从实际列表中删除元素

第二种方法可能是您出于多种原因所需的:

  • 通常对于List字段,您不想创建新的List来更改其状态。您只希望针对引用不可变对象的字段。

  • 如果某些对象在List字段上保留引用,则这些对象将引用旧对象。这是不希望的,并且会产生难以理解的副作用。

  • 创建整个过滤后的对象可能会占用CPU /内存,而从现有的List中删除对象可能会更有效。

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

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

2种方式)过滤当前对象

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

答案 1 :(得分:1)

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

来自javadoc(重点是我的)

  

删除此集合中满足给定谓词的所有元素。在迭代过程中或谓词中引发的错误或运行时异常将中继给调用方。

因此,你可以写

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

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

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

但是在此之后,您要么必须

  1. 使用上述SomeDTOfilterdList 1

  2. 创建新的new SomeDTO(someDTO.getAttrOne(), someDTO.getAttrTwo(), filterdList)
  3. 使用listAttrfilterdList)设置现有的someDTO.setListAttr(filterdList)

1 我认为您的意思是第二个实例变量的名称为attrTwo