Breaking change: the BigDecimal-based moving and running gatherers (sum, product, simple average, exponential average, median, geometric mean, standard deviation) now return BigDecimalMovingStatGatherer or BigDecimalRunningStatGatherer. The public classes they used to return are removed: BigDecimalGatherer, BigDecimalExponentialMovingAverageGatherer, BigDecimalGeometricMeanGatherer, BigDecimalMedianGatherer, BigDecimalMovingGeometricMeanGatherer, BigDecimalMovingProductGatherer, BigDecimalMovingSumGatherer, BigDecimalProductGatherer, BigDecimalSimpleAverageGatherer, BigDecimalSimpleMovingAverageGatherer, BigDecimalStandardDeviationGatherer, and BigDecimalSumGatherer. Code that only calls the factory methods on Gatherers4j is unaffected, but code that names these types (for example in a variable declaration) must change.
Breaking change: remove the public SamplePercentageGatherers.poisson(). Use Gatherers4j.samplePercentage() instead.
Behavior change: the BigDecimal gatherers now round each input to the MathContext as it arrives, and sums, means, and standard deviations then accumulate exactly instead of rounding at every step. Results can differ from v0.14.0 in the final digits. Other numeric changes:
exponentialMovingAverageWithAlpha(), exponentialMovingAverageWithPeriod(), and their By variants now round at every step. Previously they never rounded, so results gained digits with every element and long streams became progressively slower.
Sample standard deviation (Dataset.Sample) now emits nothing for the first element, where runningSampleStandardDeviation() emitted 0.
treatNullAsOne() and withMathContext() are now available on all of the BigDecimal gatherers.
Rename simpleMovingAverage(), simpleMovingAverageBy(), simpleRunningAverage(), and simpleRunningAverageBy() to movingMean(), movingMeanBy(), runningMean(), and runningMeanBy().
Replace runningPopulationStandardDeviation(), runningPopulationStandardDeviationBy(), runningSampleStandardDeviation(), and runningSampleStandardDeviationBy() with runningStandardDeviation(Dataset) and runningStandardDeviationBy(Dataset, Function).
Implement movingStandardDeviation(Dataset, int) and movingStandardDeviationBy(Dataset, int, Function).
Fix bug in sampleFixedSize() where elements were not sampled with equal probability. The first sampleSize elements were chosen too rarely and later elements too often.
Implement sampleFixedSize(int, RandomGenerator) and samplePercentage(double, RandomGenerator) so callers can specify the source of randomness.
samplePercentage() now rejects NaN, which was previously accepted and silently emitted nothing.
exponentialMovingAverageWithAlpha() and exponentialMovingAverageWithAlphaBy() now reject NaN when called, instead of failing with NumberFormatException when the stream runs.
withMathContext() on the BigDecimal gatherers now rejects a MathContext with a precision of 0, such as MathContext.UNLIMITED, which made most statistics throw ArithmeticException when the stream ran.
Implement movingHarmonicMean(), movingHarmonicMeanBy(), runningHarmonicMean(), and runningHarmonicMeanBy().
Implement movingRootMeanSquare(), movingRootMeanSquareBy(), runningRootMeanSquare(), and runningRootMeanSquareBy().
Implement movingVariance(), movingVarianceBy(), runningVariance(), and runningVarianceBy()
Implement movingStatistics(), movingStatisticsBy(), runningStatistics(), and runningStatisticsBy(), which emit a StatisticalSummary record (count, sum, mean, min, max, and population and sample variance and standard deviation) for each element.
Implement movingPercentile(), movingPercentileBy(), runningPercentile(), and runningPercentileBy().
Implement movingWeightedMean() and movingWeightedMeanBy(), the weighted moving average. Weights run linearly from 1 (oldest) to the window size (newest) by default, or can be supplied as a List<BigDecimal> (or BigDecimal... for movingWeightedMean()) ordered oldest to newest.
Fix movingProduct(), movingProductBy(), movingGeometricMean(), and movingGeometricMeanBy() accumulating rounding error over long streams. Values leaving the window are no longer divided out of the product, and each step still takes constant time.
Fix movingMin(), movingMinBy(), movingMax(), and movingMaxBy() slowing down in proportion to the window size on steadily rising or falling input, and evicting the wrong values after about 2.1 billion elements.
Fix movingGeometricMean(), runningGeometricMean(), and their By variants throwing NumberFormatException or returning wrong results when the product of the values is outside the range of a double (above about 1E+308 or below about 1E-308).
Implement movingGeometricMean(), movingGeometricMeanBy(), runningGeometricMean(), and runningGeometricMeanBy().
Implement filterNotNull(), which filters out null values from the input stream and is useful for lining up JSpecify annotations (from nullable to non-nullable).
Fix bug in movingProduct() and movingProductBy() where zero values were incorrectly handled. Addresses #184.
Change CrossGatherer, TypeFilteringGatherer, and FlattenSingleOrFail to use Greedy integrators.
Thank you to @Riggs333 for contributing code cleanups, making comparisons in FrequencyGatherer easier to understand!
Thank you to @Riggs333 for contributing changes to tests to use AssertJ’s type-specific exception assertions, which clarifies the intent of the code!
Fix and document behavior of window() when there are multiple partial groupings at the end. Addresses #135, thanks @paulk-asert!
Implement exponential moving averages with exponentialMovingAverageWithAlpha(), exponentialMovingAverageWithAlphaBy(),exponentialMovingAverageWithPeriod(), and exponentialMovingAverageWithPeriodBy().
Change index to be an int rather than a long in filterIndexed(), foldIndexed(), mapIndexed(), peekIndexed(), scanIndexed() and withIndex(). Addresses #140.
Optimize rotate(Left) to store a minimal set of elements instead of the entire stream. Addresses #141, thanks @paulk-asert!
Implement filterInstanceOf() to filter a stream by type more easily. Addresses #86, thanks @nipafx.
Implement groupOrdered(), and groupOrderedBy() to appropriately group elements in the input stream to lists in the output stream. Addresses #88, thanks @nipafx.
Implement ensureOrdered() and ensureOrderedBy() to ensure the given stream meets an ordering criteria, or fail exceptionally otherwise
Implement filterOrdered() and filterOrderedBy() to remove non-ordered elements from the input stream
Implement window() to provide more options to windowing functions, namely - ability to specify size, how many to skip each time, and whether to include partial windows
Implement repeat(n) and repeatInfinitely() to repeatedly emit the input stream to the output stream
Implement rotate(n) rotate the stream either left or right (consumes entire stream)
Renamed everyNth(n) to takeEveryNth(n) and added dropEveryNth(n) for completeness
Renamed filterWithIndex() to filterIndexed() to match other indexing Gatherers
Renamed cross() to crossWith() for consistency
Renamed interleave() to interleaveWith() for consistency
Renamed grouping() to group() and groupingBy() to groupBy() for consistency
Implement reverse() - Cause a stream to be emitted in reverse (stores entire stream in memory)
Implement maxBy(fn) and minBy(fn) - Finds the single maximum or minimum value in a stream as defined by the function given (stores entire stream in memory)
Implement exactSize(n) - Ensures a stream is precisely n elements long or throws an IllegalStateException (stores entire stream in memory)