Streamify is a small utility library that combines the power of google's Guava and Javaslang with the standard Java 8 streaming API.
Java 8 did a good job laying the ground work for a much more fluent style of coding but left a few things to be desired.
Guava's collections are extremely helpful (immutable and implementing default collection interfaces)
and Javaslang provides a much better version of Optional
(Option
) plus
additional monadic types known from functional programming (Try
, Either
, Validation
)
and a myriad of other wonderful things like Tuple
, Future
, pattern matching and a whole new collection library.
This library aims to make using and mixing them easier in standard Java 8.
<dependency>
<groupId>io.sourcy</groupId>
<artifactId>streamify</artifactId>
<version>streamifyVersion</version>
</dependency>
Streamify contains
Collector
implementations for most immutable Guava, all Javaslang, and Java default collection types, brought together in one consistent naming schemastream(data)
conversion functions to make a (Java)Stream
out of those collections and other monadic types
This basically boils down to the following usage pattern:
- Use
stream(data)
instead of the Java and Javaslang default methods. This gives you one consistent way to create a (Java)Stream
from pretty much anything. All those are Null-safe and return empty Streams instead of exploding into your face. - Use the Java streaming API and Javaslang monads to transform the stream
- You want your data back? Just use one of the provided collectors to produce a collection of your liking. No more
copyOf
,asList
,ofAll
and the other 10 different variants you can't remember when you need them.
final List<Integer> result = ImmutableList.copyOf(Arrays.stream(new Integer[]{1, 2, 2, -3})
.collect(Collectors.toList()));
As you can see there is a stream()
function that directly supports Arrays and the Stream is collected directly into a Guava ImmutableList
.
final List<Integer> result = stream(new Integer[]{1, 2, 2, -3})
.collect(toGuavaImmutableList()); // this can be shortened to toList() by another static import, read further down for details
Let's switch the key and value of a Map.
final Map<Integer, String> values = ImmutableMap.of(1, "asdf", 2, "bsdf", -3, "csdf");
final Map<String, Integer> result = values
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
Note that the stream()
functions for Collections with more than one type parameter, first and foremost Map
return a Stream<Tuple>
instead of using the tedious java default Map.Entry
interface.
final Map<Integer, String> values = ImmutableMap.of(1, "asdf", 2, "bsdf", -3, "csdf");
final Map<String, Integer> result = stream(values)
.map(t -> Tuple.of(t._2, t._1))
.collect(toGuavaImmutableMap());
You can leverage the full power of Javaslang Tuples within the streaming API.
Optional<Person> getPerson(final Integer id) {
// in reality this would maybe do some lookup somewhere
return Optional.of(new Person(id));
}
final List<Person> existingPersons = ImmutableList.copyOf(IntStream.iterate(1, i -> i + 1)
.mapToObj(Integer::valueOf)
.limit(3)
.map(this::getPerson)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList()));
Note that stream(IntStream)
also creates a Stream<Integer>
from the IntStream
. This also works for LongStream
, DoubleStream
, int[]
, long[]
and double[]
.
final List<Person> existingPersons = stream(IntStream.iterate(1, i -> i + 1))
.limit(3)
.flatMap(i -> stream(getPerson(i)))
.collect(toGuavaImmutableList());
Flatmapping the other Javaslang monadic types like Either
and Try
works exactly the same.
Just import
import static io.sourcy.streamify.Streamify.stream;
and you are ready to go.
All collectors can be statically imported without the pain of name conflicts.
A simple
import static io.sourcy.streamify.StreamifyCollectors.*;
and you will have all
toJava...()
toGuava...()
toJavaslang...()
collectors at your disposal.
If you like it short, there are 3 additional Classes you can statically import (one of them) if you want.
import static io.sourcy.streamify.StreamifyCollectors.GuavaDefaultCollectors.*;
This will give you immutable guava versions of toList()
, toMap()
and toSet()
.
If you prefer the mutable counterparts you can import
import static io.sourcy.streamify.StreamifyCollectors.JavaDefaultCollectors.*;
This will mostly give you the Java 8 default mutable collectors but with a version of toMap()
that works with Javaslang Tuples.
If you primarly use the Javaslang collections you will prefer to import
import static io.sourcy.streamify.StreamifyCollectors.JavaslangDefaultCollectors.*;
This will give you collectors for the Javaslang variants of List
, Map
and Set
.
Note: If you don't yet know Javaslang, those are NOT compatible with the java standard collections with the same name!