How to create an infinite Stream out of an Iterator?

前端 未结 4 1676
甜味超标
甜味超标 2020-12-09 03:14

Looking at the following class I\'ve made:

public class FibonacciSupplier implements Iterator {
    private final IntPredicate hasNextPredicat         


        
4条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-09 03:54

    To add another answer, perhaps AbstractSpliterator is a better choice, especially given the example code. Generate is inflexible as there is no [good] way to give a stop condition except by using limit. Limit only accepts a number of items rather than a predicate, so we have to know how many items we want to generate - which might not be possible, and what if the generator is a black box passed to us?

    AbstractSpliterator is a halfway house between having to write a whole spliterator, and using Iterator/Iterable. AbstractSpliterator lacks just the tryAdvance method where we first check our predicate for being done, and if not pass the generated value to an action. Here's an example of a Fibonacci sequence using AbstractIntSpliterator:

    public class Fibonacci {
        private static class FibonacciGenerator extends Spliterators.AbstractIntSpliterator
        {
            private IntPredicate hasNextPredicate;
            private int beforePrevious = 0;
            private int previous = 0;
    
            protected FibonacciGenerator(IntPredicate hasNextPredicate)
            {
                super(Long.MAX_VALUE, 0);
                this.hasNextPredicate = hasNextPredicate;
            }
    
            @Override
            public boolean tryAdvance(IntConsumer action)
            {
                if (action == null)
                {
                    throw new NullPointerException();
                }
    
                int next = Math.max(1, beforePrevious + previous);
                beforePrevious = previous;
                previous = next;
    
                if (!hasNextPredicate.test(next))
                {
                    return false;
                }
    
                action.accept(next);
    
                return true;
            }
    
            @Override
            public boolean tryAdvance(Consumer action)
            {
                if (action == null)
                {
                    throw new NullPointerException();
                }
    
                int next = Math.max(1, beforePrevious + previous);
                beforePrevious = previous;
                previous = next;
    
                if (!hasNextPredicate.test(next))
                {
                    return false;
                }
    
                action.accept(next);
    
                return true;
            }
        }
    
        public static void main(String args[])
        {
            Stream infiniteStream = StreamSupport.stream(
                    new FibonacciGenerator(i -> true), false);
    
            Stream finiteStream = StreamSupport.stream(
                    new FibonacciGenerator(i -> i < 100), false);
    
            // Print with a side-effect for the demo
            infiniteStream.limit(10).forEach(System.out::println);
            finiteStream.forEach(System.out::println);
        }
    } 
    

    For more details I've covered generators in Java 8 in my blog http://thecannycoder.wordpress.com/

提交回复
热议问题