首页 > 解决方案 > 首先查找多个不同集合类型的流

问题描述

public class ImmutableCrazySquares { 
   private final List<Square> xraySquare;
   private final Map<String, Set<Square>> yankeSquare
   private final Map<String, Set<Square>> zuloSquare;
    .
    .
    .
   @VisibleForTesting
   private boolean exists(String squareId) {
    boolean matches = yankeSquare.values().stream().anyMatch(squares ->
        squares.stream().anyMatch(square -> square.getId().equals(squareId)));
    if (!matches) {
        matches = xraySquare.stream()
            .anyMatch(square -> square.getId().equals(squareId));
    }
    if (!matches) {
        matches = zuloSquare.values().stream().anyMatch(squares ->
            squares.stream().anyMatch(square -> square.getId().equals(squareId)));
    }
    return matches;
   }
}

上面的类有十几个方法,但现在我只想关注这个存在的方法。本质上,我想查看 3 个集合 xraySquare、yankeSquare、zuloSquare,如果我发送的 id 在其中任何一个中,我想返回 true。遗憾的是,两个地图上的键都不是 Id,因此不能用于此操作。要获取 Id,我需要钻取值并调用 getId()。由于这是一种测试方法,因此我不想使用包含所有 id 的 adicional 集合来污染类。有没有一种简单的方法可以同时查看所有 3 个集合并在 1 找到结果后立即停止?

标签: concurrencyjava-8java-stream

解决方案


并发可能会比顺序慢,所以你的代码 IMO 就好了。可以稍微改进一下:

return 
   yankeSquare.values()
              .stream()
              .flatMap(Set::stream)
              .map(Square::getId)
              .anyMatch(Predicate.isEqual(squareId)) ||

   xraySquare.stream()
             .map(Square::getId)
             .anyMatch(Predicate.isEqual(squareId)) ||

   zuluSquare.values()
              .stream()
              .flatMap(Set::stream)
              .map(Square::getId)
              .anyMatch(Predicate.isEqual(squareId))

或者更简单,但不像你在代码中那样懒惰:

  Stream.concat(xraySquare.stream(), 
                Stream.of(yankeSquare, zuloSquare)
                      .flatMap(map -> map.values().stream().flatMap(Set::stream))
        .map(Square::getId)
        .anyMatch(Predicate.isEqual(squareId))
  )

基本上,它将您的所有收藏品展平,Stream<String>并与anyMatch


推荐阅读