【问题标题】:Stream Filter from another Stream来自另一个流的流过滤器
【发布时间】:2022-11-03 00:41:29
【问题描述】:

我正在尝试使用流过滤地图。我过滤的谓词/条件是另一个流。我目前遇到了 IllegalStateException 的问题,可能是因为我正在访问一个已经被访问过的流。

Map<Integer, Double> table = Map.of(10, 8.0,
                                    15, 10.0,
                                    20, 28.0,
                                    40, 40.0);

Stream<Double> streamDbl = getDoublefromInt(table, Stream.of(20, 40));

参考this 网站,我想出了类似下面的代码段,但它不起作用。

public static Stream<Double> getDoublefromInt(Map<Integer, Double> table, Stream<Integer> id) {
 return table.entrySet().stream
        .filter(map -> id.anyMatch(id -> id.equals(map.getKey())))
        .map(map -> map.getValue());
}

【问题讨论】:

  • 为什么要使用流过滤 Map?首先将流收集到集合/列表中怎么样?
  • 每次调用 #anyMatch 时,您都会使用第二个流。您很可能需要Set 进行快速/散列O(1) #contains 检查,而不是需要Stream 遍历的Stream
  • Stream 不是 IMO 过滤器中工作的工具。使用Set。它包含方法...contains,它自己完成您在 filter 操作中的 lambda 中的 lambda 中所做的事情。
  • 如果我正确理解了任务,那么您的解决方案就是return id.map(table::get); 在您的getDoublefromInt()

标签: java java-stream


【解决方案1】:

Stream 基本上是数据源的迭代器,它是不是数据容器(如集合)。一旦用完,就不能再使用了。出于这个原因,您会通过尝试多次触发同一个流来获得IllegalStateException

您不需要 Stream IPA 来实现您想要实现的目标,Collections 框架提供的功能就足够了。

所有繁重的工作都可以使用Collection.retainAll() 完成。

public static Stream<Double> getDoubleFromInt(Map<Integer, Double> table, Stream<Integer> id) {
    
    Set<Integer> idSet = id.collect(Collectors.toSet());
    Map<Integer, Double> copy = new HashMap<>(table);
    
    copy.keySet().retainAll(idSet);
    
    return copy.values().stream();
}

【讨论】:

    【解决方案2】:

    您可以使用流Supplier

    演示

    import java.util.Map;
    import java.util.function.Supplier;
    import java.util.stream.Stream;
    
    public class Main {
      public static void main(String[] args) {
        Map<Integer, Double> table = Map.of(
            10, 8.0,
            15, 10.0,
            20, 28.0,
            40, 40.0);
    
        Stream<Double> streamDbl = getDoublefromInt(table, () -> Stream.of(20, 40));
    
        streamDbl.forEach(System.out::println);
      }
    
      public static Stream<Double> getDoublefromInt(Map<Integer, Double> table, Supplier<Stream<Integer>> ids) {
        return table.entrySet().stream()
            .filter(map -> ids.get().anyMatch(id -> id.equals(map.getKey())))
            .map(map -> map.getValue());
      }
    }
    

    输出

    28.0
    40.0
    

    【讨论】:

      【解决方案3】:

      简单点!!!

      为什么不使用传入的Stream

      public static Stream<Double> getDoublefromInt(Map<Integer, Double> table,
                                                    Stream<Integer> ids) {
          return ids.map(id -> table.get(id))
                    .filter(Objects::nonNull());
      }
      

      看起来结果 Stream 将是相同的。

      【讨论】:

        【解决方案4】:

        我不完全明白过滤地图意味着什么?如果要从映射中获取与另一个流中指定的键相对应的值流,则解决方案很简单:

        public class Main {
            static Map<Integer, Double> table = Map.of(10, 8.0,
                    15, 10.0,
                    20, 28.0,
                    40, 40.0);
        
            public static Stream<Double> getDoubleFromInt(Map<Integer, Double> table, Stream<Integer> id) {
                return id.map(table::get);
            }
        
            public static void main(String[] args) {
                getDoubleFromInt(table, Stream.of(20, 40))
                        .forEach(System.out::println);
            }
        }
        

        印刷

        28.0
        40.0
        

        【讨论】:

          猜你喜欢
          • 2018-10-11
          • 1970-01-01
          • 1970-01-01
          • 2019-09-25
          • 2021-12-16
          • 1970-01-01
          • 2016-07-14
          相关资源
          最近更新 更多