diff --git a/README.md b/README.md index 807d997..203814c 100644 --- a/README.md +++ b/README.md @@ -6,34 +6,55 @@ A library of useful [Stream Gatherers](https://openjdk.org/jeps/473) (custom int TBD, once I start publishing snapshots to Maven Central. +# Gatherers In This Library + + +| Function | Purpose | +|----------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `averageBigDecimals()` | Create a running or trailing average of `BigDecimal` values. See below for options.
See [specific advice on averaging](#averaging-bigdecimal-objects) | +| `averageBigDecimalsBy(fn)` | Create a running avergage of `BigDecimal` values mapped out of some different object via `fn`.
See [specific advice on averaging](#averaging-bigdecimal-objects) | +| `dedupeConsecutive()` | Remove conescutive duplicates from a stream | +| `dedupeConsecutiveBy(fn)` | Remove consecutive duplicates from a stream as returned by `fn` | +| `distinctBy(fn)` | Emit only distinct elements from the stream, as measured by `fn` | +| `interleave(stream)` | Creates a stream of alternating objects from the input stream and the argument stream | +| `last(n)` | Constrain the stream to the last `n` values | +| `withIndex()` | Maps all elements of the stream as-is, along with their 0-based index. | +| `zipWith(stream)` | Creates a stream of `Pair` objects whose values come from the input stream and argument stream | +| `zipWithNext()` | Creates a stream of `List` objects via a sliding window of width 2 and stepping 1 | | + + # Use Cases -(Example, TODO clean this up) +#### Running average of `Stream` -**Running Average** +For more options, please see the [specific advice on averaging](#averaging-bigdecimal-objects). ```java Stream - .of(new BigDecimal("1.0"), new BigDecimal("2.0"), new BigDecimal("10.0")) + .of("1.0", "2.0", "10.0") + .map(BigDecimal::new) .gather(Gatherers4j.averageBigDecimals()) .toList(); // [1, 1.5, 4.3333333333333333] ``` -**Trailing Average** +#### Moving average of `Stream` + +For more options, please see the [specific advice on averaging](#averaging-bigdecimal-objects) ```java Stream - .of(new BigDecimal("1.0"), new BigDecimal("2.0"), new BigDecimal("10.0"), new BigDecimal("20.0"), new BigDecimal("30.0")) - .gather(Gatherers4j.averageBigDecimals().trailing(2)) + .of("1.0", "2.0", "10.0", "20.0", "30.0") + .map(BigDecimal::new) + .gather(Gatherers4j.averageBigDecimals().simpleMovingAverage(2)) .toList(); // [1.5, 6, 15, 25] ``` -**Removing consecutive duplicate elements:** +#### Remove consecutive duplicate elements ```java Stream @@ -44,7 +65,52 @@ Stream // ["A", "B", "C", "D", "A", "B", "C"] ``` -**Limit the stream to the `last` _n_ elements:** +#### Remove consecutive duplicate elements, where duplicate is measured by a function + +```java +record Person(String firstName, String lastName) {} + +Stream + .of( + new Person("Todd", "Ginsberg"), + new Person("Emma", "Ginsberg"), + new Person("Todd", "Smith") + ) + .gather(Gatherers4j.dedupeConsecutiveBy(Person::firstName)) + .toList(); + +// [Person("Todd", "Ginsberg"), Person("Todd", "Smith")] +``` + +#### Remove duplicate elements, where duplicate is measured by a function + +```java +record Person(String firstName, String lastName) {} + +Stream + .of( + new Person("Todd", "Ginsberg"), + new Person("Emma", "Ginsberg"), + new Person("Todd", "Smith") + ) + .gather(Gatherers4j.distinctBy(Person::firstName)) + .toList(); + +// [Person("Todd", "Ginsberg"), Person("Emma", "Ginsberg")] +``` + +#### Interleave streams of the same type into one stream + +```java +final Stream left = Stream.of("A", "B", "C"); +final Stream right = Stream.of("D", "E", "F"); + +left.gather(Gatherers4j.interleave(right)).toList(); + +// ["A", "D", "B", "E", "C", "F"] +``` + +#### Limit the stream to the `last` _n_ elements ```java Stream @@ -55,8 +121,104 @@ Stream // ["E", "F", "G"] ``` +#### Include index with original stream values + +```java +Stream + .of("A", "B", "C") + .gather(Gatherers4j.withIndex()) + .toList(); + +// [IndexedValue(0, "A"), IndexedValue(1, "B"), IndexedValue(2, "C")] +``` + +#### Zip two streams of together into a `Stream` + +The left and right streams can be of different types. + +```java +final Stream left = Stream.of("A", "B", "C"); +final Stream right = Stream.of(1, 2, 3); + +left.gather(Gatherers4j.zip(right)).toList(); + +// [Pair("A", 1), Pair("B", 2), Pair("C", 3)] + +``` + +#### Zip elements of a stream together + +This converts a `Stream` to a `Stream>` + +```java +Stream + .of("A", "B", "C", "D", "E") + .gather(Gatherers4j.zipWitNext()) + .toList(); + +// [["A", "B"], ["B", "C"], ["C", "D"], ["D", "E"]] +``` + +## Averaging `BigDecimal` objects + +Functions on `AveragingBigDecimalGatherer` which modify the output. + +| Function | Purpose | +|----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `simpleMovingAverage(window)` | Instead of a cumulative average, calculate a moving average over a trailing `window` | +| `includePartialValues` | When calculating a moving average, include partially calculated values when less than `window` number of values are availabe.
The default is to only include fully calculated averages. | +| `treatNullAsZero()` | When an element in the `Stream` is `null` treat it as `BigDecimal.ZERO` instead of skipping it in the calculation. | +| `treatNullAs(BigDecimal)` | When an element in the `Stream` is `null` treat it as the `BigDecimal` value given instead of skipping it in the calculation. | +| `withMathContext(MathContext)` | Switch the `MathContext` for all calculations to the non-null `MathContext` given. The default is `MathContext.DECIMAL64`. | +| `withRoundingMode(RoundingMode)` | Switch the `RoundingMode` for all calcullations to the non-null `RoundingMode` given. The default is `RoundingMode.HALF_UP`. | +| `withOriginal()` | Include the original value (either a `BigDecimal` or some other object type if using `averageBigDecimalsBy()`) with the calculated average. | + +### Example of `averageBigDecimals()` + +This example creates a stream of `double`, converts each value to a `BigDecmial`, and takes a `simpleMovingAverage` over 10 trailing values. +It will `includePartialValues` and sets the `RoundingMode` and `MathContext` to the values given. Additionally, nulls +are treated as zeros, and the calculated average is returned along with the original value. + +```java +someStreamOfBigDecimal() + .gather(Gatherers4j + .averageBigDecimals() + .simpleMovingAverage(10) + .includePartialValues() + .withRoundingMode(RoundingMode.HALF_EVEN) + .withMathContext(MathContext.DECIMAL32) + .treatNullAsZero() + .withOriginal() + ) + .toList(); + +// Example output: +[ + WithOriginal[original=0.8462487, calculated=0.8462487], + WithOriginal[original=0.8923297, calculated=0.8692890], + WithOriginal[original=0.2556937, calculated=0.6647573], + WithOriginal[original=0.2901778, calculated=0.5711125], + WithOriginal[original=0.4945578, calculated=0.5558016], + WithOriginal[original=0.3173066, calculated=0.5160525], + WithOriginal[original=0.6377766, calculated=0.5334417], + WithOriginal[original=0.1729199, calculated=0.4883765], + WithOriginal[original=0.7408201, calculated=0.5164258], + WithOriginal[original=0.7169926, calculated=0.5364825], + WithOriginal[original=0.5174489, calculated=0.5036025], + WithOriginal[original=0.5895662, calculated=0.4733262], + WithOriginal[original=0.4458275, calculated=0.4923396], + // etc... +] +``` + +# Project Philosophy + +1. Consider adding a gatherer if it cannot be implemented with `map`, `filter`, or a collector without enclosing outside state. +2. Resist the temptation to add functions that only exist to provide an alias. They seem fun/handy but add surface area to the API and must be maintained forever. +3. All features should be documented and tested. + # Contributing -Guidance forthcoming. +Please feel free to file issues for change requests or bugs. If you would like to contribute new functionality, please contact me before starting work! Copyright © 2024 by Todd Ginsberg \ No newline at end of file diff --git a/src/main/java/com/ginsberg/gatherers4j/AveragingBigDecimalGatherer.java b/src/main/java/com/ginsberg/gatherers4j/AveragingBigDecimalGatherer.java index b5dfc25..dadc931 100644 --- a/src/main/java/com/ginsberg/gatherers4j/AveragingBigDecimalGatherer.java +++ b/src/main/java/com/ginsberg/gatherers4j/AveragingBigDecimalGatherer.java @@ -33,7 +33,7 @@ public class AveragingBigDecimalGatherer private RoundingMode roundingMode = RoundingMode.HALF_UP; private MathContext mathContext = MathContext.DECIMAL64; private BigDecimal nullReplacement; - private int trailingCount = 1; + private int windowSize = 1; private boolean includePartialValues; AveragingBigDecimalGatherer(final Function mappingFunction) { @@ -43,7 +43,7 @@ public class AveragingBigDecimalGatherer @Override public Supplier initializer() { - return trailingCount == 1 ? State::new : () -> new TrailingState(trailingCount); + return windowSize == 1 ? State::new : () -> new TrailingState(windowSize); } @Override @@ -60,40 +60,73 @@ public Integrator integrat }; } - public AveragingBigDecimalGatherer trailing(int count) { - if (count <= 0) { - throw new IllegalArgumentException("Trailing count must be positive"); + /** + * Construct a moving average, with a window of size window. + * + * @param window The size of the window to average values over, must be a positive number. + */ + public AveragingBigDecimalGatherer simpleMovingAverage(int window) { + if (window <= 0) { + throw new IllegalArgumentException("Moving window size must be positive"); } - trailingCount = count; + windowSize = window; return this; } - public AveragingBigDecimalGatherer includePartialTailingValues() { + /** + * When creating a moving average and the full size of the window has not yet been reached, the + * gatherer should emit averages for what it has. + * For example, if the trailing average is over 10 values, but the stream has only emitted two + * values, the gatherer should average the two values and emit the answer. The default is to not + * emit anything until the full size of the window has been seen. + */ + public AveragingBigDecimalGatherer includePartialValues() { includePartialValues = true; return this; } + /** + * When encountering a null value in a stream, treat it as `BigDecimal.ZERO` instead. + */ public AveragingBigDecimalGatherer treatNullAsZero() { return treatNullAs(BigDecimal.ZERO); } + /** + * When encountering a null value in a stream, treat it as the given `rule` value instead. + * + * @param rule The value to replace null with + */ public AveragingBigDecimalGatherer treatNullAs(final BigDecimal rule) { this.nullReplacement = rule; return this; } + /** + * Replace the MathContext used for all mathematical operations in this class. + * + * @param mathContext A non-null MathContext + */ public AveragingBigDecimalGatherer withMathContext(final MathContext mathContext) { mustNotBeNull(mathContext, "MathContext must not be null"); this.mathContext = mathContext; return this; } + /** + * Replace the RoundingMode used for all mathematical operations in this class. + * + * @param roundingMode A non-null RoundingMode + */ public AveragingBigDecimalGatherer withRoundingMode(final RoundingMode roundingMode) { mustNotBeNull(roundingMode, "RoundingMode must not be null"); this.roundingMode = roundingMode; return this; } + /** + * Include the original input value from the stream in addition to the calculated average. + */ public WithOriginalGatherer withOriginal() { return new WithOriginalGatherer<>(this); } diff --git a/src/main/java/com/ginsberg/gatherers4j/GathererUtils.java b/src/main/java/com/ginsberg/gatherers4j/GathererUtils.java index 4c6f349..84b04cf 100644 --- a/src/main/java/com/ginsberg/gatherers4j/GathererUtils.java +++ b/src/main/java/com/ginsberg/gatherers4j/GathererUtils.java @@ -17,7 +17,7 @@ public class GathererUtils { - public static boolean safeEquals(final Object left, final Object right) { + static boolean safeEquals(final Object left, final Object right) { if (left == null && right == null) { return true; } else if (left == null || right == null) { @@ -26,7 +26,7 @@ public static boolean safeEquals(final Object left, final Object right) { return left.equals(right); } - public static void mustNotBeNull(final Object subject, final String message) { + static void mustNotBeNull(final Object subject, final String message) { if (subject == null) { throw new IllegalArgumentException(message); } diff --git a/src/main/java/com/ginsberg/gatherers4j/Gatherers4j.java b/src/main/java/com/ginsberg/gatherers4j/Gatherers4j.java index e7fe61e..ab473e2 100644 --- a/src/main/java/com/ginsberg/gatherers4j/Gatherers4j.java +++ b/src/main/java/com/ginsberg/gatherers4j/Gatherers4j.java @@ -18,11 +18,12 @@ import java.math.BigDecimal; import java.util.List; -import java.util.Objects; import java.util.function.Function; import java.util.stream.Gatherer; import java.util.stream.Stream; +import static com.ginsberg.gatherers4j.GathererUtils.mustNotBeNull; + public class Gatherers4j { /** @@ -61,23 +62,30 @@ public static AveragingBigDecimalGatherer averageBigDecimalsBy( } /** + * Remove consecutive duplicates from a stream where duplication is measured by the given function. + * * @param function A mapping function used to compare objects in the stream for equality. */ public static Gatherer dedupeConsecutiveBy(final Function function) { - Objects.requireNonNull(function, "Mapping function cannot be null"); + mustNotBeNull(function, "Mapping function cannot be null"); return new DedupeConsecutiveGatherer<>(function); } /** - * Filter a stream to only distinct elements as described by the given function. + * Filter a stream to only distinct elements as described by the given function. * - * @param function The mapping function + * @param function The non-null mapping function */ public static Gatherer distinctBy(final Function function) { - Objects.requireNonNull(function, "Mapping function cannot be null"); // TODO: Where should this go? + mustNotBeNull(function, "Mapping function cannot be null"); return new DistinctGatherer<>(function); } + /** + * Creates a stream of alternating objects from the input stream and the argument stream + * + * @param other A non-null stream to interleave + */ public static Gatherer interleave(final Stream other) { return new InterleavingGatherer<>(other); } @@ -91,19 +99,25 @@ public static LastGatherer last(final int count) { return new LastGatherer<>(count); } - public static Gatherer> mapWithIndex(final Function mappingFunction) { - Objects.requireNonNull(mappingFunction, "Mapping function cannot be null"); - return new IndexingGatherer<>(mappingFunction); - } - + /** + * Maps all elements of the stream as-is, along with their 0-based index. + */ public static Gatherer> withIndex() { - return new IndexingGatherer<>(Function.identity()); + return new IndexingGatherer<>(); } - public static Gatherer> zip(final Stream other) { - return new ZipGatherer<>(other); + /** + * Creates a stream of `Pair` objects whose values come from the input stream and argument stream + * + * @param other A non-null stream to zip with + */ + public static Gatherer> zipWith(final Stream other) { + return new ZipWithGatherer<>(other); } + /** + * Creates a stream of `List` objects via a sliding window of width 2 and stepping 1 + */ public static Gatherer> zipWithNext() { return new ZipWithNextGatherer<>(); } diff --git a/src/main/java/com/ginsberg/gatherers4j/IndexingGatherer.java b/src/main/java/com/ginsberg/gatherers4j/IndexingGatherer.java index cc0a7ac..3b80260 100644 --- a/src/main/java/com/ginsberg/gatherers4j/IndexingGatherer.java +++ b/src/main/java/com/ginsberg/gatherers4j/IndexingGatherer.java @@ -16,17 +16,13 @@ package com.ginsberg.gatherers4j; -import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Gatherer; -public class IndexingGatherer - implements Gatherer> { +public class IndexingGatherer + implements Gatherer> { - private final Function mappingFunction; - - IndexingGatherer(final Function function) { - this.mappingFunction = function; + IndexingGatherer() { } @Override @@ -35,9 +31,9 @@ public Supplier initializer() { } @Override - public Integrator> integrator() { + public Integrator> integrator() { return (state, element, downstream) -> downstream - .push(new IndexedValue<>(state.index++, mappingFunction.apply(element))); + .push(new IndexedValue<>(state.index++, element)); } public static class State { diff --git a/src/main/java/com/ginsberg/gatherers4j/ZipGatherer.java b/src/main/java/com/ginsberg/gatherers4j/ZipWithGatherer.java similarity index 89% rename from src/main/java/com/ginsberg/gatherers4j/ZipGatherer.java rename to src/main/java/com/ginsberg/gatherers4j/ZipWithGatherer.java index c842a67..f0f4daf 100644 --- a/src/main/java/com/ginsberg/gatherers4j/ZipGatherer.java +++ b/src/main/java/com/ginsberg/gatherers4j/ZipWithGatherer.java @@ -21,10 +21,10 @@ import java.util.stream.Gatherer; import java.util.stream.Stream; -public class ZipGatherer implements Gatherer> { +public class ZipWithGatherer implements Gatherer> { private final Spliterator otherSpliterator; - ZipGatherer(final Stream other) { + ZipWithGatherer(final Stream other) { Objects.requireNonNull(other, "Other stream must not be null"); otherSpliterator = other.spliterator(); } diff --git a/src/test/java/com/ginsberg/gatherers4j/AveragingBigDecimalGathererTest.java b/src/test/java/com/ginsberg/gatherers4j/AveragingBigDecimalGathererTest.java index a4b08d9..803bee6 100644 --- a/src/test/java/com/ginsberg/gatherers4j/AveragingBigDecimalGathererTest.java +++ b/src/test/java/com/ginsberg/gatherers4j/AveragingBigDecimalGathererTest.java @@ -185,7 +185,7 @@ void treatNullAsNonZero() { } @Test - void trailingAverageOfBigDecimals() { + void simpleMovingAverageAverageOfBigDecimals() { // Arrange final Stream input = Stream.of( new BigDecimal("1.0"), @@ -197,7 +197,7 @@ void trailingAverageOfBigDecimals() { // Act final List output = input - .gather(Gatherers4j.averageBigDecimals().trailing(2)) + .gather(Gatherers4j.averageBigDecimals().simpleMovingAverage(2)) .toList(); // Assert @@ -212,7 +212,7 @@ void trailingAverageOfBigDecimals() { } @Test - void trailingAverageOfBigDecimalsWithPartials() { + void simpleMovingAverageAverageOfBigDecimalsWithPartials() { // Arrange final Stream input = Stream.of( new BigDecimal("1.0"), @@ -224,7 +224,7 @@ void trailingAverageOfBigDecimalsWithPartials() { // Act final List output = input - .gather(Gatherers4j.averageBigDecimals().trailing(2).includePartialTailingValues()) + .gather(Gatherers4j.averageBigDecimals().simpleMovingAverage(2).includePartialValues()) .toList(); // Assert @@ -355,16 +355,16 @@ void mathContextCannotBeNull() { } @Test - void trailingInvalidRangeZero() { + void simpleMovingAverageInvalidRangeZero() { assertThatThrownBy(() -> - Stream.of(BigDecimal.ONE).gather(Gatherers4j.averageBigDecimals().trailing(0)) + Stream.of(BigDecimal.ONE).gather(Gatherers4j.averageBigDecimals().simpleMovingAverage(0)) ).isExactlyInstanceOf(IllegalArgumentException.class); } @Test - void trailingInvalidRangeNegative() { + void simpleMovingAverageInvalidRangeNegative() { assertThatThrownBy(() -> - Stream.of(BigDecimal.ONE).gather(Gatherers4j.averageBigDecimals().trailing(-1)) + Stream.of(BigDecimal.ONE).gather(Gatherers4j.averageBigDecimals().simpleMovingAverage(-1)) ).isExactlyInstanceOf(IllegalArgumentException.class); } diff --git a/src/test/java/com/ginsberg/gatherers4j/DedupeConsecutiveGatherersTest.java b/src/test/java/com/ginsberg/gatherers4j/DedupeConsecutiveGatherersTest.java index 8a52fc8..8ff5e57 100644 --- a/src/test/java/com/ginsberg/gatherers4j/DedupeConsecutiveGatherersTest.java +++ b/src/test/java/com/ginsberg/gatherers4j/DedupeConsecutiveGatherersTest.java @@ -21,6 +21,7 @@ import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class DedupeConsecutiveGatherersTest { @@ -90,4 +91,15 @@ record TestConsecutive(int left, String right) { new TestConsecutive(6, "C") ); } + + + @Test + void dedupeConsecutiveByWithNullMappingFunction() { + // Arrange + final Stream input = Stream.of("A"); + + // Act/Assert + assertThatThrownBy(() -> input.gather(Gatherers4j.dedupeConsecutiveBy(null)).toList()) + .isExactlyInstanceOf(IllegalArgumentException.class); + } } \ No newline at end of file diff --git a/src/test/java/com/ginsberg/gatherers4j/DistinctGathererTest.java b/src/test/java/com/ginsberg/gatherers4j/DistinctGathererTest.java index f0b83ef..0a7736a 100644 --- a/src/test/java/com/ginsberg/gatherers4j/DistinctGathererTest.java +++ b/src/test/java/com/ginsberg/gatherers4j/DistinctGathererTest.java @@ -22,6 +22,7 @@ import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class DistinctGathererTest { @@ -52,4 +53,14 @@ void distinctByWithNull() { // Assert assertThat(output).containsExactly(null, "a"); } + + @Test + void distinctByWithNullMappingFunction() { + // Arrange + final Stream input = Stream.of("A"); + + // Act/Assert + assertThatThrownBy(() -> input.gather(Gatherers4j.distinctBy(null)).toList()) + .isExactlyInstanceOf(IllegalArgumentException.class); + } } \ No newline at end of file diff --git a/src/test/java/com/ginsberg/gatherers4j/IndexingGathererTest.java b/src/test/java/com/ginsberg/gatherers4j/IndexingGathererTest.java index 4f65649..fd87920 100644 --- a/src/test/java/com/ginsberg/gatherers4j/IndexingGathererTest.java +++ b/src/test/java/com/ginsberg/gatherers4j/IndexingGathererTest.java @@ -16,7 +16,6 @@ package com.ginsberg.gatherers4j; -import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.List; @@ -26,105 +25,42 @@ class IndexingGathererTest { - @Nested - class MapWithIndex { - @Test - void mapObjectWithIndex() { - // Arrange - final Stream input = Stream.of("A", "B", "C"); - - // Act - final List> output = input - .gather(Gatherers4j.mapWithIndex(String::toLowerCase)) - .toList(); - - // Assert - assertThat(output) - .containsExactly( - new IndexedValue<>(0, "a"), - new IndexedValue<>(1, "b"), - new IndexedValue<>(2, "c") - ); - } - - @Test - void mapIntegerWithIndex() { - // Arrange - final Stream input = Stream.of(1, 2, 3); - - // Act - final List> output = input - .gather(Gatherers4j.mapWithIndex(it -> it * it)) - .toList(); - - // Assert - assertThat(output) - .containsExactly( - new IndexedValue<>(0, 1), - new IndexedValue<>(1, 4), - new IndexedValue<>(2, 9) - ); - } - - @Test - void mapIntegerToStringWithIndex() { - // Arrange - final Stream input = Stream.of(1, 2, 3); - - // Act - final List> output = input - .gather(Gatherers4j.mapWithIndex(it -> String.valueOf(it * it))) - .toList(); - - // Assert - assertThat(output) - .containsExactly( - new IndexedValue<>(0, "1"), - new IndexedValue<>(1, "4"), - new IndexedValue<>(2, "9") - ); - } + @Test + void objectWithIndex() { + // Arrange + final Stream input = Stream.of("A", "B", "C"); + + // Act + final List> output = input + .gather(Gatherers4j.withIndex()) + .toList(); + + // Assert + assertThat(output) + .containsExactly( + new IndexedValue<>(0, "A"), + new IndexedValue<>(1, "B"), + new IndexedValue<>(2, "C") + ); } - @Nested - class WithIndex { - @Test - void objectWithIndex() { - // Arrange - final Stream input = Stream.of("A", "B", "C"); - - // Act - final List> output = input - .gather(Gatherers4j.withIndex()) - .toList(); - - // Assert - assertThat(output) - .containsExactly( - new IndexedValue<>(0, "A"), - new IndexedValue<>(1, "B"), - new IndexedValue<>(2, "C") - ); - } - - @Test - void integerWithIndex() { - // Arrange - final Stream input = Stream.of(1, 2, 3); - - // Act - final List> output = input - .gather(Gatherers4j.withIndex()) - .toList(); - - // Assert - assertThat(output) - .containsExactly( - new IndexedValue<>(0, 1), - new IndexedValue<>(1, 2), - new IndexedValue<>(2, 3) - ); - } + @Test + void integerWithIndex() { + // Arrange + final Stream input = Stream.of(1, 2, 3); + + // Act + final List> output = input + .gather(Gatherers4j.withIndex()) + .toList(); + + // Assert + assertThat(output) + .containsExactly( + new IndexedValue<>(0, 1), + new IndexedValue<>(1, 2), + new IndexedValue<>(2, 3) + ); } } \ No newline at end of file diff --git a/src/test/java/com/ginsberg/gatherers4j/ZipGathererTest.java b/src/test/java/com/ginsberg/gatherers4j/ZipWithGathererTest.java similarity index 91% rename from src/test/java/com/ginsberg/gatherers4j/ZipGathererTest.java rename to src/test/java/com/ginsberg/gatherers4j/ZipWithGathererTest.java index 325612f..5eef0ed 100644 --- a/src/test/java/com/ginsberg/gatherers4j/ZipGathererTest.java +++ b/src/test/java/com/ginsberg/gatherers4j/ZipWithGathererTest.java @@ -23,7 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class ZipGathererTest { +class ZipWithGathererTest { @Test void zipGatherer() { @@ -33,7 +33,7 @@ void zipGatherer() { // Act final List> output = left - .gather(Gatherers4j.zip(right)) + .gather(Gatherers4j.zipWith(right)) .toList(); // Assert @@ -53,7 +53,7 @@ void zipGathererOtherEmpty() { // Act final List> output = left - .gather(Gatherers4j.zip(right)) + .gather(Gatherers4j.zipWith(right)) .toList(); // Assert @@ -68,7 +68,7 @@ void interleavingGathererThisEmpty() { // Act final List> output = left - .gather(Gatherers4j.zip(right)) + .gather(Gatherers4j.zipWith(right)) .toList(); // Assert