All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.obermuhlner.math.big.stream.BigDecimalStream Maven / Gradle / Ivy

There is a newer version: 2.3.2
Show newest version
package ch.obermuhlner.math.big.stream;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Comparator;
import java.util.Spliterator;
import java.util.Spliterators.AbstractSpliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import ch.obermuhlner.math.big.BigDecimalMath;

/**
 * Provides constructor methods for streams of {@link BigDecimal} elements. 
 */
public class BigDecimalStream {

    /**
     * Returns a sequential ordered {@code Stream} from {@code startInclusive}
     * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
     *
     * 

An equivalent sequence of increasing values can be produced * sequentially using a {@code for} loop as follows: *

for (BigDecimal i = startInclusive; i.compareTo(endExclusive) < 0; i = i.add(step, mathContext)) {
    // ...
}
* * @param startInclusive the (inclusive) initial value * @param endExclusive the exclusive upper bound * @param step the step between elements * @param mathContext the {@link MathContext} used for all mathematical operations * @return a sequential {@code Stream} */ public static Stream range(BigDecimal startInclusive, BigDecimal endExclusive, BigDecimal step, MathContext mathContext) { if (step.signum() == 0) { throw new IllegalArgumentException("invalid step: 0"); } if (endExclusive.subtract(startInclusive).signum() != step.signum()) { return Stream.empty(); } return StreamSupport.stream(new BigDecimalSpliterator(startInclusive, endExclusive, false, step, mathContext), false); } /** * Returns a sequential ordered {@code Stream} from {@code startInclusive} * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}. * *

The {@code long} arguments are converted using {@link BigDecimal#valueOf(long)}.

* * @param startInclusive the (inclusive) initial value * @param endExclusive the exclusive upper bound * @param step the step between elements * @param mathContext the {@link MathContext} used for all mathematical operations * @return a sequential {@code Stream} * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext) */ public static Stream range(long startInclusive, long endExclusive, long step, MathContext mathContext) { return range(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endExclusive), BigDecimal.valueOf(step), mathContext); } /** * Returns a sequential ordered {@code Stream} from {@code startInclusive} * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}. * *

The {@code double} arguments are converted using {@link BigDecimal#valueOf(double)}.

* * @param startInclusive the (inclusive) initial value * @param endExclusive the exclusive upper bound * @param step the step between elements * @param mathContext the {@link MathContext} used for all mathematical operations * @return a sequential {@code Stream} * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext) */ public static Stream range(double startInclusive, double endExclusive, double step, MathContext mathContext) { return range(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endExclusive), BigDecimal.valueOf(step), mathContext); } /** * Returns a sequential ordered {@code Stream} from {@code startInclusive} * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}. * *

An equivalent sequence of increasing values can be produced * sequentially using a {@code for} loop as follows: *

for (BigDecimal i = startInclusive; i.compareTo(endInclusive) <= 0; i = i.add(step, mathContext)) {
    // ...
}
* * @param startInclusive the (inclusive) initial value * @param endInclusive the inclusive upper bound * @param step the step between elements * @param mathContext the {@link MathContext} used for all mathematical operations * @return a sequential {@code Stream} * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext) */ public static Stream rangeClosed(BigDecimal startInclusive, BigDecimal endInclusive, BigDecimal step, MathContext mathContext) { if (step.signum() == 0) { throw new IllegalArgumentException("invalid step: 0"); } if (endInclusive.subtract(startInclusive).signum() == -step.signum()) { return Stream.empty(); } return StreamSupport.stream(new BigDecimalSpliterator(startInclusive, endInclusive, true, step, mathContext), false); } /** * Returns a sequential ordered {@code Stream} from {@code startInclusive} * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}. * *

The {@code long} arguments are converted using {@link BigDecimal#valueOf(long)}.

* * @param startInclusive the (inclusive) initial value * @param endInclusive the inclusive upper bound * @param step the step between elements * @param mathContext the {@link MathContext} used for all mathematical operations * @return a sequential {@code Stream} * @see #rangeClosed(BigDecimal, BigDecimal, BigDecimal, MathContext) */ public static Stream rangeClosed(long startInclusive, long endInclusive, long step, MathContext mathContext) { return rangeClosed(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endInclusive), BigDecimal.valueOf(step), mathContext); } /** * Returns a sequential ordered {@code Stream} from {@code startInclusive} * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}. * *

The {@code double} arguments are converted using {@link BigDecimal#valueOf(double)}.

* * @param startInclusive the (inclusive) initial value * @param endInclusive the inclusive upper bound * @param step the step between elements * @param mathContext the {@link MathContext} used for all mathematical operations * @return a sequential {@code Stream} * @see #rangeClosed(BigDecimal, BigDecimal, BigDecimal, MathContext) */ public static Stream rangeClosed(double startInclusive, double endInclusive, double step, MathContext mathContext) { return rangeClosed(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endInclusive), BigDecimal.valueOf(step), mathContext); } private static class BigDecimalSpliterator extends AbstractSpliterator { private BigDecimal value; private BigDecimal step; private long count; private MathContext mathContext; public BigDecimalSpliterator(BigDecimal startInclusive, BigDecimal step, long count, MathContext mathContext) { super(count, Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED | Spliterator.SORTED); this.value = startInclusive; this.step = step; this.count = count; this.mathContext = mathContext; } public BigDecimalSpliterator(BigDecimal startInclusive, BigDecimal end, boolean inclusive, BigDecimal step, MathContext mathContext) { this(startInclusive, step, estimatedCount(startInclusive, end, inclusive, step, mathContext), mathContext); } private static long estimatedCount(BigDecimal startInclusive, BigDecimal end, boolean inclusive, BigDecimal step, MathContext mathContext) { BigDecimal count = end.subtract(startInclusive).divide(step, mathContext); long result = count.longValue(); if (BigDecimalMath.fractionalPart(count).signum() != 0) { result++; } else { if (inclusive) { result++; } } return result; } @Override public Comparator getComparator() { if (step.signum() < 0) { return Comparator.reverseOrder(); } return null; } @Override public boolean tryAdvance(Consumer action) { if (count == 0) { return false; } action.accept(value); value = value.add(step, mathContext); count--; return true; } @Override public void forEachRemaining(Consumer action) { while (count > 0) { action.accept(value); value = value.add(step, mathContext); count--; } } @Override public Spliterator trySplit() { long firstHalfCount = count / 2; if (firstHalfCount == 0) { return null; } long secondHalfCount = count - firstHalfCount; count = firstHalfCount; BigDecimal startSecondHalf = value.add(step.multiply(new BigDecimal(firstHalfCount), mathContext), mathContext); return new BigDecimalSpliterator(startSecondHalf, step, secondHalfCount, mathContext); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy