Skip to content

Gluing code to connect the marvellous types from javaslang with java 8 streams and guava immutable collections.

License

Notifications You must be signed in to change notification settings

sourcy/streamify

Repository files navigation

Build Status codecov.io Maven Central Join the chat at https://gitter.im/sourcy/streamify

Streamify

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.

Maven

<dependency>
    <groupId>io.sourcy</groupId>
    <artifactId>streamify</artifactId>
    <version>streamifyVersion</version>
</dependency>

What can i do with it?

Streamify contains

  • Collector implementations for most immutable Guava, all Javaslang, and Java default collection types, brought together in one consistent naming schema
  • stream(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.

Examples

Collecting into an immutable List

Plain Java

final List<Integer> result = ImmutableList.copyOf(Arrays.stream(new Integer[]{1, 2, 2, -3})
  .collect(Collectors.toList()));

Streamify

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

Working with Maps

Let's switch the key and value of a Map.

Plain Java

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));

Streamify

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.

Flatmapping Optional/Option into a Stream

Optional<Person> getPerson(final Integer id) {
  // in reality this would maybe do some lookup somewhere
  return Optional.of(new Person(id));
}

Plain Java

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()));

Streamify

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.

I want this! What do i need to do?

Stream conversion

Just import

import static io.sourcy.streamify.Streamify.stream;

and you are ready to go.

Collectors

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!

About

Gluing code to connect the marvellous types from javaslang with java 8 streams and guava immutable collections.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages