org.paumard::more-spliterators

More Spliterators is a set of operations written on Java 8 Streams. It allows several basic operations that are not available in the the Java 8, and that have proven to be very useful in some cases.

License

License

GroupId

GroupId

org.paumard
ArtifactId

ArtifactId

more-spliterators
Last Version

Last Version

0.2
Release Date

Release Date

Type

Type

jar
Description

Description

org.paumard::more-spliterators
More Spliterators is a set of operations written on Java 8 Streams. It allows several basic operations that are not available in the the Java 8, and that have proven to be very useful in some cases.
Project URL

Project URL

http://github.com/JosePaumard/more-spliterators
Source Code Management

Source Code Management

https://github.com/JosePaumard/more-spliterators

Download more-spliterators

How to add to project

<!-- https://jarcasting.com/artifacts/org.paumard/more-spliterators/ -->
<dependency>
    <groupId>org.paumard</groupId>
    <artifactId>more-spliterators</artifactId>
    <version>0.2</version>
</dependency>
// https://jarcasting.com/artifacts/org.paumard/more-spliterators/
implementation 'org.paumard:more-spliterators:0.2'
// https://jarcasting.com/artifacts/org.paumard/more-spliterators/
implementation ("org.paumard:more-spliterators:0.2")
'org.paumard:more-spliterators:jar:0.2'
<dependency org="org.paumard" name="more-spliterators" rev="0.2">
  <artifact name="more-spliterators" type="jar" />
</dependency>
@Grapes(
@Grab(group='org.paumard', module='more-spliterators', version='0.2')
)
libraryDependencies += "org.paumard" % "more-spliterators" % "0.2"
[org.paumard/more-spliterators "0.2"]

Dependencies

test (2)

Group / Artifact Type Version
org.testng : testng jar 6.9.6
org.assertj : assertj-core jar 3.1.0

Project Modules

There are no modules declared in this project.

More spliterators

Basically, a classical stream operation can only work on the current element of the given stream, but cannot take into account the previous elements.

The right solution is to change the stream itself. Suppose we have a stream {a, b, c, d, ...} and that we need to remember the value of a when we process b. The problem can be solved by changing this stream to the following : {[a, b], [b, c], [c, d], ...}. We go from a stream of objects to a stream of pairs of objects, or maybe a stream of streams of objects.

This problem can be solved by creating a spliterator on the original stream spliterator. This is the object of this API.

The entry point of this API is meant to be the MoreSpliterators factory class. Reading the Javadoc is a good idea, patterns are provided.

You can use this API directly with Maven, by adding the following dependency.

<dependency>
    <groupId>org.paumard</groupId>
    <artifactId>more-spliterators</artifactId>
    <version>0.2</version>
</dependency>

Operations provided

Cycling

Takes a stream and repeats it forever, as long as this stream has a finite size.

Grouping

Takes a stream [a, b, c, d] and returns [[a, b], [c, d]]. The grouping factor is parametrized.

Repeating

Takes a stream [a, b, c, d] and returns [a, a, b, b, c, c, d, d]. The repeating factor is parametrized.

Rolling

Takes a stream [a, b, c, d, e] and returns [[a, b], [b, c], [c, d], [d, e]]. The rolling factor is parametrized.

Traversing

Takes a set of streams and builds a stream of substreams. Each substream is made of the nth element of the corresponding stream. For instance, if we have:

stream0 = ["a00", "a01", "a02", "a03"]
stream1 = ["a10", "a11", "a12", "a13"]
stream2 = ["a20", "a21", "a22", "a23"]
stream3 = ["a30", "a31", "a32", "a33"]

The resulting stream is the following:

[["a00", "a10", "a20", "a30"],
 ["a01", "a11", "a21", "a31"],
 ["a02", "a12", "a22", "a32"],
 ["a03", "a13", "a23", "a33"]]

Validating

A validating spliterator works with a predicate and two mapping functions. When the predicate applied to the current element of the stream is true, then the first mapper is applied to that element. If it is false, then the second mapper is applied. In both cases the mapped element is added to the new spliterator.

This validating spliterator could also be implemented with a mapping function.

Interrupting

The interrupting spliterator takes an interruptor as a parameter. If this interruptor became false for a given element of the provided stream, then it ends the returned stream.

It has been created to handle the following case. We created an iterating stream on a class hierarchy:

String<Class<?>> streamOfClasses = Stream.iterate(myClass, c -> c == null ? null : c.getSuperclass());

The problem is that, once the Object.class has been met, this stream is null. We wanted to stop it. This is exactly what the interrupting spliterator does.

Stream<Class<?>> interruptedStreamOfClasses = MoreSpliterator.interrupting(streamOfClasses, Objects::isNull);

The returned stream in this case will generate elements up to Object.class and will stop.

Gating

The gating spliterator does the opposite of the interrupting spliterator. Here we provide a validator. The returned stream will transmit the elements of the input stream one the provided validator has seen a valid element.

Weaving

The weaving operator is another version of the traversing operator, it could be seen as a traversing followed by a flatmap. Here is an example:

stream0 = ["a00", "a01", "a02", "a03"]
stream1 = ["a10", "a11", "a12", "a13"]
stream2 = ["a20", "a21", "a22", "a23"]
stream3 = ["a30", "a31", "a32", "a33"]

The resulting stream is the following:

["a00", "a10", "a20", "a30", "a01", "a11", "a21", "a31",
 "a02", "a12", "a22", "a32", "a03", "a13", "a23", "a33"]

Zipping

The zipping operator takes two streams and a bifunction. The resulting stream is the application of the bifunction on two elements of the streams, one at a time.

Acknowledgements

Many thanks to Rémi Forax for his valuable advice during the development of this API.

Now Rémi you can implement FizzBuzz using the following code:

Stream<String> fizzBuzz = 
   zip(
      IntStream.range(0, 101).boxed(), 
      zip(
         cycle(Stream.of("fizz", "", "")), 
         cycle(Stream.of("buzz, "", "", "", ""))
         String::concat
      ), 
      (i, string) -> string.isEmpty() ? i.toString() : string
   );
fizzBuzz.skip(1).forEach(System.out::println);

Versions

Version
0.2
0.1