首页 > 解决方案 > 我有两个列表,我想根据 groovy 或 java 中其他列表中存在的 id 过滤列表

问题描述

第一个列表->

 List<Stat> stats = statService.loadAllStatsByCompanyAndDateStatsFetched(company.uuid, sDate, eDate)

第二个列表->

Page<Asset> assets = assetService.fetchAllAssetByAssetUuids(assetUuids, pageable)
List<Asset> assetList = asset.getContent()

Stat有一个变量assetUuid Asset有一个List<Stat> 现在我想在assetList的Asset中添加stat如果assetUuid匹配

    class Asset {
              List<Stat> stats =[]
              @Id
             String assetUuid
      }

class Stat { String assetUuid }

假设我有 10 个 Stats 对象,其中 2 个 stats 对象具有相同的assetUuid。现在我想获取具有相同assetUuid的2个统计数据并列出一个列表,然后将其设置为asset.stats = 2 stats object

现在写我是这样实现的,有没有其他使用java流的有效方法

assets.getContent().each { asset ->
    List<Stat> stats = []
    stats.each { stat ->
        if (stat.assetUUID == asset.uuid)
            stats.add(stat)
    }
    asset.stats = stats
}

标签: javagroovyjava-stream

解决方案


  1. 将列表转换为Asset地图
  2. 迭代列表Stat并将统计信息添加到匹配资产。

假设Asset有一个像这样实现的方法addStat

// class Asset
List<Stat> stats;

public Asset addStat(Stat stat) {
    if (null == stats) {
        stats = new ArrayList<>();
    }
    stats.add(stat);
    return this;
}

Map::computeIfPresent如下使用会很方便

Map<AssetUuid, Asset> assetMap = assetList.stream() // Stream<Asset>
        .collect(Collectors.toMap(Asset::getUuid, asset -> asset, (a1, a2) -> a1));

stats.forEach(stat -> 
    assetMap.computeIfPresent(stat.getAssetUuid(), (k, v) -> v.addStat(stat))
);

// or like this using lambda
stats.forEach(stat ->
        assetMap.computeIfPresent(stat.getAssetUuid(), (k, v) -> { 
            v.getStats().add(stat); 
            return v;
        }) 
);

如果新匹配的 stats 应该覆盖那些 in asset,这可以这样实现(假设有一个 setter Asset::setStats):

Map<AssetUuid, List<Stat>> mapStats = stats.stream()
        .collect(Collectors.groupingBy(Stat::getAssetUuid));

// overwrite only lists of stat only in matched assets
assetList.stream()
        .map(asset -> mapStats.containsKey(asset.getAssetUuid()))
        .forEach(asset -> asset.setStats(mapStats.get(asset.getAssetUuid())));

// overwrite lists of stat in all assets (non-matched with an empty list)
assetList.stream()
        .forEach(asset -> asset.setStats(mapStats.getOrDefault(
            asset.getAssetUuid(), Collections.emptyList()
        )));

推荐阅读