【问题标题】:Limit IntStream.iterate to a specific value将 IntStream.iterate 限制为特定值
【发布时间】:2019-07-31 18:43:48
【问题描述】:

我正在生成,比如说,以下范围:

IntStream.iterate(1, i -> 3*i)

如何将流限制为特定的元素值,例如100(不使用limit()计算元素)?

谢谢!

UPDATE函数可以是任意的

【问题讨论】:

标签: java java-8 java-stream


【解决方案1】:

如果您还不能使用 Java 9,可以使用以下对三参数 IntStream.iterate 的重新实现:

public static IntStream iterate(int seed, IntPredicate hasNext, IntUnaryOperator next) {
    Objects.requireNonNull(next); Objects.requireNonNull(hasNext);
    return StreamSupport.intStream(
        new Spliterators.AbstractIntSpliterator(
            Long.MAX_VALUE, Spliterator.ORDERED|Spliterator.NONNULL) {
        private IntUnaryOperator op = i -> { op = next; return i; };
        private int value = seed;

        @Override
        public boolean tryAdvance(IntConsumer action) {
            Objects.requireNonNull(action);
            if(op == null) return false;
            int t = op.applyAsInt(value);
            if(!hasNext.test(t)) { op = null; return false; }
            action.accept(value = t);
            return true;
        }

        @Override
        public void forEachRemaining(IntConsumer action) {
            Objects.requireNonNull(action);
            IntUnaryOperator first = op;
            if(first == null) return;
            op = null;
            for(int t = first.applyAsInt(value); hasNext.test(t); t = next.applyAsInt(t))
                action.accept(t);
        }
    }, false);
}

它的工作方式类似于 Java 9 的 IntStream.iterate,不同之处在于您必须更改要调用 static 方法的类(或修改 import static 语句):

iterate(1, i -> i < 100, i -> i*3).forEach(System.out::println);
1
3
9
27
81

【讨论】:

  • 这很酷但是哇.. 这么多代码.. 好吧,我想至少在我的情况下我会解决它,至少除非我有 Java 8
【解决方案2】:

一种新方法

Stream<T> iterate​(T seed,Predicate<? super T> hasNext,UnaryOperator<T> next)

在 Java-9 中引入。因此,从该版本开始,可以执行以下操作:

IntStream.iterate(1, i -> i < 100, i -> 3*i)

这将产生1 3 9 27 81

【讨论】:

  • 好的,这似乎是我要找的东西。但是 Java 8 呢?
  • @DmitrySenkovich:Java Stream API 已在 Java 8 中引入。
  • @Nikolas 我的意思是这个谓词hasNext
  • @DmitrySenkovich,Java-9 中添加了重载的迭代方法
  • @Aominè,这只会产生1 3 9 27 81
【解决方案3】:

作为其他答案的补充,如果您已经可以使用,则还有另一种可能使用Stream#takeWhilePredicate 作为参数。

测试

jshell> IntStream.iterate(1, i -> 3 * i).takeWhile(i -> i < 100).toArray();
$3 ==> int[5] { 1, 3, 9, 27, 81 }

【讨论】:

    【解决方案4】:
    IntStream.range(0, N).forEach(this::doSomething);
    
    
    int[] arr = IntStream.range(start, end).toArray();
    

    【讨论】:

    • 这个例子不是关于增加 3 本身,可能有一个随机函数。我需要限制值
    • 也许我太愚蠢了,抱歉:) 但我不明白你:问题是我不知道限制(在你的情况下是 N)但我有一个函数和一个初始值
    猜你喜欢
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 2015-02-12
    • 2019-04-24
    相关资源
    最近更新 更多