import java.math.BigInteger; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.function.Supplier; import java.util.function.UnaryOperator; import java.util.stream.Stream; abstract public class NumericStreamFactory { private NumericStreamFactory() { throw new IllegalStateException("Not expecting to create instances of this class"); } public static Stream getFibonacciStreamOfLongValues() { return Stream.generate(new Supplier() { private int _elementNumber = 0; private long _priorValueOne = 0; private long _priorValueTwo = 0; private boolean _exceedsLongValue = false; @Override public Long get() { ++_elementNumber; final long nextValue = _priorValueOne + ((_priorValueTwo == 0) ? 1 : _priorValueTwo); _priorValueOne = _priorValueTwo; _priorValueTwo = nextValue; if (nextValue < 0 || _exceedsLongValue) { _exceedsLongValue = true; throw new NoSuchElementException("Fibonacci element number " + _elementNumber + " exceeds the maximum value that can be held in a Java 'long' type."); } return nextValue; } }); } public static Stream getFibonacciStreamOfBigIntegerValues() { return Stream.generate(new Supplier() { private BigInteger _priorValueOne = null; private BigInteger _priorValueTwo = BigInteger.ZERO; @Override public BigInteger get() { final BigInteger nextValue; if (_priorValueOne == null) { nextValue = BigInteger.ONE; } else { nextValue = _priorValueOne.add(_priorValueTwo); } _priorValueOne = _priorValueTwo; _priorValueTwo = nextValue; return nextValue; } }); } public static Stream getPrimeStream() { return Stream.generate(new Supplier() { private int _lastPrime = 2 - 1; // = one before the first known prime number private List _primeNumbers = new ArrayList<>(); @Override public Integer get() { int candidatePrime = _lastPrime + 1; boolean tryAnotherNumber = true; while (tryAnotherNumber) { tryAnotherNumber = false; for (final Integer factor : _primeNumbers) { if (candidatePrime % factor == 0) { ++candidatePrime; tryAnotherNumber = true; break; } } } _primeNumbers.add(candidatePrime); _lastPrime = candidatePrime; return candidatePrime; } }); } public static Stream getCombinedStreamOfLongValues() { return Stream.generate(new Supplier() { private boolean nextIsPrime = false; final Iterator fibonacciStreamIterator = getFibonacciStreamOfLongValues().iterator(); final Iterator primeStreamIterator = getPrimeStream().iterator(); @Override public Long get() { if (nextIsPrime) { nextIsPrime = false; return (long) primeStreamIterator.next(); } else { nextIsPrime = true; return fibonacciStreamIterator.next(); } } }); } public static Stream getCombinedStreamOfBigIntegerValues() { return Stream.generate(new Supplier() { private boolean nextIsPrime = false; final Iterator fibonacciStreamIterator = getFibonacciStreamOfBigIntegerValues().iterator(); final Iterator primeStreamIterator = getPrimeStream().iterator(); @Override public BigInteger get() { if (nextIsPrime) { nextIsPrime = false; return new BigInteger(String.valueOf(primeStreamIterator.next())); } else { nextIsPrime = true; return fibonacciStreamIterator.next(); } } }); } }