【问题标题】:Lambda expression for supplier to generate IntStream供应商生成 IntStream 的 Lambda 表达式
【发布时间】:2018-12-01 15:07:39
【问题描述】:

如何将此处的Supplier 代码替换为 lambda 表达式

IntStream inStream = Stream.generate(new Supplier<Integer>() {
    int x= 1;
    @Override
    public Integer get() {
        return x++ ;
    }
}).limit(10).mapToInt(t -> t.intValue());
inStream.forEach(System.out::println);

上面这段代码的输出是:

1
2
3
4
5
6
7
8
9
10

【问题讨论】:

    标签: java lambda java-8 java-stream


    【解决方案1】:

    Stream::generate 不适用于此问题。根据文档:

    这适用于生成常量流、随机元素流等

    • 你可能想用IntStream::range:

      IntStream intStream = IntStream.range(1, 11);
      intStream.forEach(System.out::println);
      
    • 另一种解决方案可能是使用IntStream.iterate,您可以使用IntUnaryOperator轻松控制增量:

      IntStream intStream = IntStream.iterate(1, i -> i+1).limit(10);
      intStream.forEach(System.out::println);
      
    • 如前所述,Stream::generate 适用于恒定流或随机元素。随机元素可能会使用 Random 类获得,因此您可能希望使用 AtomicInteger 获得增量:

      AtomicInteger atomicInteger = new AtomicInteger(1);
      IntStream intStream = Stream.generate(atomicInteger::getAndIncrement).limit(10);
      intStream.forEach(System.out::println);
      

    【讨论】:

    • 谢谢@nikolas。 IntStream.range(1, 11) 简洁大方。我想我也会使用 lambda。
    • 哦,我错过了。不要在流中改变变量,i -&gt; ++ii -&gt; i+1 会更好。
    • 可能只是我,但我觉得IntStream.rangeClosed(1, 10);IntStream.range(1, 11); 更适合这项任务。在生成数组/列表索引等的情况下,range 函数将是理想的函数。但无论如何我猜都是选择问题。
    • @Nikolas 很公平,这就是为什么我提到“可能只是我......”。我想我们在这个问题上达成了一致......“选择问题”;-)。
    • 在这里写IntStream.rangeClosed(1, 10) 可能更自然。而且,顺便说一句,首先使用IntStream.generate(new AtomicInteger(1)::getAndIncrement) .limit(10),会使.mapToInt(Integer::intValue) 拆箱步骤过时。
    【解决方案2】:

    或者你可以使用这个

    IntStream.iterate(1, i -> i + 1)
     .limit(10)
     .forEach(System.out::println);  
    

    【讨论】:

    • 是的,我更喜欢这个而不是generate,然后是iterate 的Java9 版本。 (+1)
    • 使用 IntStream.iterate 代替 Stream.iterate 以提高效率。
    【解决方案3】:

    如果你一定要专门使用Stream.generate,这样的事情:

    IntStream inStream = Stream.generate(new AtomicInteger(1)::getAndIncrement)
            .limit(10)
            .mapToInt(t -> t);
    inStream.forEach(System.out::println);
    

    编辑:使用IntStream.generate,您可以将其执行为

    IntStream.generate(new AtomicInteger(1)::getAndIncrement).limit(10);
    

    注意:就 API 设计而言,更好的解决方案肯定是针对此类用例使用 Stream.iterate

    【讨论】:

    • @secretsuperstar 是的,我忽略了 x 在那里被视为原子。现已更新。
    • 我喜欢 new AtomicInteger(1)::getAndIncrement 方法参考 - 太舒服了:)
    • 首先使用IntStream.generate(new AtomicInteger(1)::getAndIncrement) .limit(10),使.mapToInt(t -&gt; t)拆箱步骤过时。
    • @Holger 好点,但我使用了问题中发布的Stream.generate。我相信这需要我map 这是必须的。
    • 我不明白为什么你必须在这里使用map。 OP 显示代码最终生成 IntStream,因此,值得指出的是,首先创建 Stream&lt;Integer&gt;,然后再调用 .mapToInt(t -&gt; t),比直接创建更复杂效率低-前进的方法。如果你真的需要Stream&lt;Integer&gt;,使用IntStream.generate(new AtomicInteger(1)::getAndIncrement) .limit(10) .boxed() 仍然比使用map 更简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多