如何使用 Java 8 根据条件从项目页面内的集合中删除元素

How to remove an element from a Set inside a Page of items based on a Condition using Java 8

我有一个 Page of Farmers 来自 JPA 存储库 调用 findAll 方法。每个 Farmer 由 SetFarms 组成,它们也像这样进入存储库调用:

public class Farmer {

private String name;
@ManyToMany
@JoinTable(name = "farmer_asset", joinColumns = @JoinColumn(name = "farmer_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "asset_id", referencedColumnName = "id"))
private Set<Asset> assets;
}

Asset有一个叫isActive的属性表示资产是否活跃;

在我 FarmersPage 中,我只想 select 活跃的农民资产;

我试过 @WhereJoinTable(clause = "is_active ='true'")

但是,我了解到 is_active 属性 应该处于中间 ManyToMany 关系 Table farmer_asset

现在我无法更改实体结构,并使用 @WhereJoinTable(clause = "is_active ='true'")

因此,我想到在进行 JPA 调用后尝试过滤这些值。

但是,遍历每个 Farmer,然后删除 inActive Assets,然后将其添加回页面并维护页面元素似乎过于性能繁重的操作。

我尝试使用正常的 Java 代码,看起来像这样:


Page<Farmer> farmers = farmerRepository.findAll(pageable);

List<Farmer> farmersList = new LinkedList<>();

for (FarmerDto eachFarmer : farmers.getContent()) {

   Set<Asset> eachFarmerAssets = 
   eachFarmer.getAssets();

   eachFarmerAssets.removeIf(e -> 
   !e.getIsActive());

   eachFarmer.setAssets(eachFarmerAssets);              
   
   farmersList.add(eachFarmer);
               }
         return new PageImpl<FarmerDto>(farmersList, pageable, farmers.getTotalElements());

我想这样做 Java 8 使用流,但我无法迭代列表并更改其元素,而元素又是 Set<Asset>

来这里寻求一些建议。

提前致谢。

您实际上不会将相同的引用重新分配给 Set<Asset>,因为即使集合已被修改,它仍然是特定农民“已知”的同一对象。

并且您绝对不需要流来完成此任务。文档建议在设计流 pipe-lines.

时避免有状态操作和 side-effects

相反,您可以在列表上使用 forEach() 方法:

Page<Farmer> farmers = farmerRepository.findAll(pageable);
List<Farmer> farmersList = new farmers.getContent();
    
farmersList.forEach(farmer -> farmer.getAssets()
    .removeIf(e -> !e.getIsActive()));

您必须按照以下步骤操作:

  1. 检索农民实体列表
  2. 将实体列表转换为 farmer dtos 列表
  3. 每个农民 dto
    1. 填写数据
    2. 放入活跃的断言列表
List<Farmer> farmers = farmerRepository.findAll(pageable).getContent(); //1
List<FarmerDto> farmersList = farmers.stream() // 2
        .map(farmer -> { // 3
            FarmerDto farmerDto = new FarmerDto();
            // fill farmerDto 3.1
            farmerDto.setAssets(farmer.getAssets().stream().filter(Farmer::getIsActive()).toList()); //3.2
            return farmerDto;
        }).toList();
return new PageImpl<FarmerDto>(farmersList, pageable, farmers.getTotalElements());