Skip to content

Commit

Permalink
Added Stream.mapMulti and Stream.mapMultiTo*
Browse files Browse the repository at this point in the history
  • Loading branch information
diamondobama committed Mar 22, 2021
1 parent c1255df commit 463263b
Show file tree
Hide file tree
Showing 16 changed files with 624 additions and 292 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ CN1-Stream
A lightweight Stream API from Java 8 rewritten on iterators for Codename One. Adapted from LSA, refactored, and cleaned up for CN1 compatibility.


### Includes
## Includes

+ Functional interfaces (`Supplier`, `Function`, `Consumer` etc);
+ `Stream`/`IntStream`/`LongStream`/`DoubleStream` (without parallel processing, but with a variety of additional methods and with custom operators);
Expand All @@ -20,7 +20,7 @@ A lightweight Stream API from Java 8 rewritten on iterators for Codename One. Ad
+ `Objects` from Java 7.


### Usage
## Usage

```java
Stream.of(/* array | list | set | map | anything based on Iterator/Iterable interface */)
Expand Down Expand Up @@ -157,6 +157,19 @@ In addition to back-ported Java 8 Stream operators, the library provides:
.mapIndexed((i, s) -> s + Integer.toString(i)) // [a0, b1, c2]
```

- `mapMulti` / `mapMultiToInt` / `mapMultiToLong` / `mapMultiToDouble` - applies a mapper function to each element for producing replacing elements

```java
Stream.of(1, 2, 3, 4)
.mapMulti((a, consumer) -> {
consumer.accept(a); // value
consumer.accept(-a); // negated value
if (a % 2 == 0) {
consumer.accept(a * 2); // multiply even value by 2
}
}) // [1, -1, 2, -2, 4, 3, -3, 4, -4, 8]
```


### Throwable functions

Expand Down
18 changes: 9 additions & 9 deletions src/group/diamonddev/Collectors.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public void accept(List<T> t, T u) {
* @param <T> the type of the input elements
*
* @return a {@code Collector}
* @since 1.2.0
* @since 1.0.0
*/
public static <T> Collector<T, ?, List<T>> toUnmodifiableList() {
return Collectors.collectingAndThen(Collectors.<T>toList(), new UnaryOperator<List<T>>() {
Expand Down Expand Up @@ -139,7 +139,7 @@ public void accept(Set<T> set, T t) {
* @param <T> the type of the input elements
*
* @return a {@code Collector}
* @since 1.2.0
* @since 1.0.0
*/
public static <T> Collector<T, ?, Set<T>> toUnmodifiableSet() {
return Collectors.collectingAndThen(Collectors.<T>toSet(), new UnaryOperator<Set<T>>() {
Expand Down Expand Up @@ -252,7 +252,7 @@ public void accept(M map, T t) {
*
* @return a {@code Collector}
* @see #toUnmodifiableMap(Function, Function, BinaryOperator)
* @since 1.2.0
* @since 1.0.0
*/
public static <T, K, V> Collector<T, ?, Map<K, V>> toUnmodifiableMap(
final Function<? super T, ? extends K> keyMapper,
Expand All @@ -277,7 +277,7 @@ public void accept(M map, T t) {
* values associated with the same key
*
* @return a {@code Collector}
* @since 1.2.0
* @since 1.0.0
*/
public static <T, K, V> Collector<T, ?, Map<K, V>> toMap(
final Function<? super T, ? extends K> keyMapper,
Expand Down Expand Up @@ -305,7 +305,7 @@ public void accept(M map, T t) {
* @param mapFactory a supplier function that provides new {@code Map}
*
* @return a {@code Collector}
* @since 1.2.0
* @since 1.0.0
*/
public static <T, K, V, M extends Map<K, V>> Collector<T, ?, M> toMap(
final Function<? super T, ? extends K> keyMapper,
Expand Down Expand Up @@ -341,7 +341,7 @@ public void accept(M map, T t) {
* values associated with the same key
*
* @return a {@code Collector}
* @since 1.2.0
* @since 1.0.0
*/
public static <T, K, V> Collector<T, ?, Map<K, V>> toUnmodifiableMap(
final Function<? super T, ? extends K> keyMapper,
Expand Down Expand Up @@ -970,7 +970,7 @@ public void accept(Map<K, A> map, T t) {
* @param predicate a predicate used for classifying input elements
*
* @return a {@code Collector}
* @since 1.1.9
* @since 1.0.0
*/
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(
Predicate<? super T> predicate) {
Expand All @@ -988,7 +988,7 @@ public void accept(Map<K, A> map, T t) {
* @param downstream the collector of partitioned elements
*
* @return a {@code Collector}
* @since 1.1.9
* @since 1.0.0
*/
public static <T, D, A> Collector<T, ?, Map<Boolean, D>> partitioningBy(
final Predicate<? super T> predicate,
Expand Down Expand Up @@ -1038,7 +1038,7 @@ public Map<Boolean, D> apply(Tuple2<A> container) {
* @param merger the function which merges two results into the single one
*
* @return a {@code Collector}
* @since 1.2.2
* @since 1.0.0
*/
public static <T, R1, R2, R> Collector<T, ?, R> teeing(
final Collector<? super T, ?, R1> downstream1,
Expand Down
72 changes: 58 additions & 14 deletions src/group/diamonddev/DoubleStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import group.diamonddev.internal.Compose;
import group.diamonddev.internal.Operators;
import group.diamonddev.internal.Params;
import group.diamonddev.internal.SpinedBuffer;
import group.diamonddev.iterator.PrimitiveIndexedIterator;
import group.diamonddev.iterator.PrimitiveIterator;
import group.diamonddev.operator.*;
Expand Down Expand Up @@ -161,7 +162,7 @@ public static DoubleStream iterate(final double seed,
*
* @return the new stream
* @throws NullPointerException if {@code op} is null
* @since 1.1.5
* @since 1.0.0
*/
public static DoubleStream iterate(
final double seed,
Expand Down Expand Up @@ -210,12 +211,12 @@ public static DoubleStream concat(
*
* @param a the first stream
* @param b the second stream
* @param rest the other streams
* @param rest the rest of streams
*
* @return the new concatenated stream
* @throws NullPointerException if {@code a} or {@code b}
* or {@code rest} is null
* @since 1.2.2
* @since 1.0.0
*/
public static DoubleStream concat(
final DoubleStream a,
Expand Down Expand Up @@ -250,7 +251,7 @@ public PrimitiveIterator.OfDouble iterator() {
}

/**
* Applies custom operator on stream.
* Applies a custom operator on a stream.
* <p>
* Transforming function can return {@code DoubleStream} for intermediate operations,
* or any value for terminal operation.
Expand Down Expand Up @@ -335,7 +336,7 @@ public <R> R custom(final Function<DoubleStream, R> function) {
* Returns a {@code Stream} consisting of the elements of this stream,
* each boxed to an {@code Double}.
*
* <p>This is an lazy intermediate operation.
* <p>This is a lazy intermediate operation.
*
* @return a {@code Stream} consistent of the elements of this stream,
* each boxed to an {@code Double}
Expand All @@ -360,7 +361,7 @@ public Stream<Double> boxed() {
*
* @return the new stream
* @see #concat(DoubleStream, DoubleStream)
* @since 1.2.2
* @since 1.0.0
*/
public DoubleStream prepend(DoubleStream stream) {
return DoubleStream.concat(stream, this);
Expand All @@ -382,7 +383,7 @@ public DoubleStream prepend(DoubleStream stream) {
*
* @return the new stream
* @see #concat(DoubleStream, DoubleStream)
* @since 1.2.2
* @since 1.0.0
*/
public DoubleStream append(DoubleStream stream) {
return DoubleStream.concat(this, stream);
Expand Down Expand Up @@ -617,6 +618,31 @@ public DoubleStream flatMap(final DoubleFunction<? extends DoubleStream> mapper)
return new DoubleStream(params, new DoubleFlatMap(iterator, mapper));
}

/**
* Returns a stream consisting of the results of replacing each element of
* this stream with the contents of a mapped stream produced by applying
* the provided mapping function to each element.
*
* <p>This is an intermediate operation.
*
* @param mapper the mapper function used to apply to each element for producing replacing elements
*
* @return the new stream
* @see Stream#mapMulti(group.diamonddev.function.BiConsumer)
* @see DoubleStream#flatMap(group.diamonddev.function.DoubleFunction)
* @since 1.0.1
*/
public DoubleStream mapMulti(final DoubleMapMultiConsumer mapper) {
return flatMap(new DoubleFunction<DoubleStream>() {
@Override
public DoubleStream apply(double value) {
SpinedBuffer.OfDouble buffer = new SpinedBuffer.OfDouble();
mapper.accept(value, buffer);
return DoubleStream.of(buffer.iterator());
}
});
}

/**
* Returns a stream consisting of the distinct elements of this stream.
*
Expand Down Expand Up @@ -932,7 +958,7 @@ public void forEachIndexed(int from, int step,

/**
* Performs a reduction on the elements of this stream, using the provided
* identity value and an associative accumulation function, and returns the
* identity value, and an associative accumulation function, and returns the
* reduced value.
*
* <p>The {@code identity} value must be an identity for the accumulator
Expand Down Expand Up @@ -1114,7 +1140,7 @@ public OptionalDouble average() {
* Tests whether all elements match the given predicate.
* May not evaluate the predicate on all elements if not necessary
* for determining the result. If the stream is empty then
* {@code false} is returned and the predicate is not evaluated.
* {@code false} is returned, and the predicate is not evaluated.
*
* <p>This is a short-circuiting terminal operation.
*
Expand Down Expand Up @@ -1146,7 +1172,7 @@ public boolean anyMatch(DoublePredicate predicate) {
* Tests whether all elements match the given predicate.
* May not evaluate the predicate on all elements if not necessary for
* determining the result. If the stream is empty then {@code true} is
* returned and the predicate is not evaluated.
* returned, and the predicate is not evaluated.
*
* <p>This is a short-circuiting terminal operation.
*
Expand All @@ -1164,7 +1190,7 @@ public boolean anyMatch(DoublePredicate predicate) {
* @param predicate the predicate used to match elements
*
* @return {@code true} if either all elements of the stream match the
* provided predicate or the stream is empty, otherwise {@code false}
* provided predicate, or the stream is empty, otherwise {@code false}
*/
public boolean allMatch(DoublePredicate predicate) {
while (iterator.hasNext()) {
Expand All @@ -1178,7 +1204,7 @@ public boolean allMatch(DoublePredicate predicate) {
* Tests whether no elements match the given predicate.
* May not evaluate the predicate on all elements if not necessary for
* determining the result. If the stream is empty then {@code true} is
* returned and the predicate is not evaluated.
* returned, and the predicate is not evaluated.
*
* <p>This is a short-circuiting terminal operation.
*
Expand All @@ -1196,7 +1222,7 @@ public boolean allMatch(DoublePredicate predicate) {
* @param predicate the predicate used to match elements
*
* @return {@code true} if either no elements of the stream match the
* provided predicate or the stream is empty, otherwise {@code false}
* provided predicate, or the stream is empty, otherwise {@code false}
*/
public boolean noneMatch(DoublePredicate predicate) {
while (iterator.hasNext()) {
Expand Down Expand Up @@ -1231,7 +1257,7 @@ public OptionalDouble findFirst() {
* @param other the other element to return if stream is empty
*
* @return first element or {@code other} if stream is empty
* @since 1.2.2
* @since 1.0.0
*/
public double findFirstOrElse(double other) {
if (iterator.hasNext()) {
Expand Down Expand Up @@ -1360,4 +1386,22 @@ public void close() {
params.closeHandler = null;
}
}

/**
* Represents an operation on two input arguments.
*
* @see #mapMulti(group.diamonddev.DoubleStream.DoubleMapMultiConsumer)
* @since 1.0.1
*/
public interface DoubleMapMultiConsumer {

/**
* Replaces the given {@code value} with zero or more values
* by feeding the mapped values to the {@code consumer} consumer.
*
* @param value the double value coming from upstream
* @param consumer a {@code DoubleConsumer} accepting the mapped values
*/
void accept(double value, DoubleConsumer consumer);
}
}
10 changes: 5 additions & 5 deletions src/group/diamonddev/Exceptional.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public T getOrElse(T other) {
* @param other the supplier function that produces value if there were any exception
*
* @return inner value if there were no exceptions, otherwise value produced by supplier function
* @since 1.1.9
* @since 1.0.0
*/
public T getOrElse(Supplier<? extends T> other) {
return throwable == null ? value : other.get();
Expand Down Expand Up @@ -196,7 +196,7 @@ public Exceptional<T> or(Supplier<Exceptional<T>> supplier) {
*
* @return a result of the transforming function
* @throws NullPointerException if {@code function} is null
* @since 1.1.9
* @since 1.0.0
*/
public <R> R custom(Function<Exceptional<T>, R> function) {
Objects.requireNonNull(function);
Expand Down Expand Up @@ -230,7 +230,7 @@ public <U> Exceptional<U> map(ThrowableFunction<? super T, ? extends U, Throwabl
* @param consumer a consumer function
*
* @return this {@code Exceptional}
* @since 1.1.2
* @since 1.0.0
*/
public Exceptional<T> ifPresent(Consumer<? super T> consumer) {
if (throwable == null) {
Expand Down Expand Up @@ -280,7 +280,7 @@ public <E extends Throwable> Exceptional<T> ifExceptionIs(Class<E> throwableClas
* @return this {@code Exceptional} if there were no exceptions, otherwise
* an {@code Exceptional} with wrapped recovering function result
* @throws NullPointerException if {@code function} is null
* @since 1.1.2
* @since 1.0.0
*/
public Exceptional<T> recover(final ThrowableFunction<Throwable, ? extends T, Throwable> function) {
if (throwable == null) return this;
Expand All @@ -302,7 +302,7 @@ public Exceptional<T> recover(final ThrowableFunction<Throwable, ? extends T, Th
* @return this {@code Exceptional} if there were no exceptions, otherwise
* an {@code Exceptional} produced by recovering function
* @throws NullPointerException if {@code function} or produced result is null
* @since 1.1.2
* @since 1.0.0
*/
public Exceptional<T> recoverWith(final Function<Throwable, ? extends Exceptional<T>> function) {
if (throwable == null) return this;
Expand Down
2 changes: 1 addition & 1 deletion src/group/diamonddev/IntPair.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* @param <T> the type of the second element
*
* @author Diamond
* @since 1.1.2
* @since 1.0.0
*/
public final class IntPair<T> {

Expand Down
Loading

0 comments on commit 463263b

Please sign in to comment.