functional-reactive
Made in the European Union

Utility Functions

String, Stream, Exception, Converting and SystemProperties helpers.

The com.svenruppert.functional package collects small, focused utility classes. Each one is an interface of static methods โ€” no instances, no state.

StreamFunctions

static <T> Function<Predicate<T>, Function<Stream<T>, Stream<T>>> streamFilter();

Curried filter so you can build stream pipelines without needing the stream yet:

Function<String, Predicate<Car>> brandFilter = brand -> car -> car.brand().equals(brand);

Function<Predicate<Car>, Function<Stream<Car>, Stream<Car>>> sf = StreamFunctions.streamFilter();

sf.apply(brandFilter.apply("BMW"))
  .apply(carRepository.stream())
  .forEach(System.out::println);

Often combined with andThen for fully declarative pipelines:

brandFilter
    .andThen(StreamFunctions.streamFilter())
    .apply("BMW")
    .apply(carRepository.stream());

ExceptionFunctions

static Function<Exception, String>                       message();
static Function<Exception, Stream<StackTraceElement>>    toStackTraceStream();

message() is what every Checked* interface uses internally to render a failure reason โ€” falling back to the simple class name when getMessage() is null.

String reason = ExceptionFunctions.message().apply(ex);

ExceptionFunctions.toStackTraceStream()
    .apply(ex)
    .limit(5)
    .forEach(System.err::println);

Converting

static <T> Function<T, Result<String>>  convertToString();
static <T> Function<T, Result<String>>  convertToString(Function<T, String> func);

static <T> Function<T, Result<Boolean>> convertToBoolean();
static <T> Function<T, Result<Boolean>> convertToBoolean(Function<T, Boolean> func);

static <T> Function<T, Result<Integer>> convertToInteger();
static <T> Function<T, Result<Integer>> convertToInteger(Function<T, Integer> func);

static <T> Function<T, Result<Double>>  convertToDouble();
static <T> Function<T, Result<Double>>  convertToDouble(Function<T, Double> func);

Each conversion returns a Result so exceptions during the conversion become a Failure:

Function<String, Result<Integer>> toInt = Converting.convertToInteger(Integer::parseInt);

toInt.apply("42").ifPresentOrElse(
    System.out::println,                       // 42
    err -> System.err.println("nope: " + err)
);

The no-arg overloads pick a default converter for that target type.

SystemProperties

Read system properties safely โ€” every method returns a Result, so unset or malformed values surface as Failure instead of null/NumberFormatException.

static Function<String, Result<String>>  systemProperty(Class qualifier);
static Function<String, Result<String>>  systemProperty(Class qualifier, String defaultValue);
static Function<String, Result<Boolean>> systemPropertyBoolean(Class qualifier);
static Function<String, Result<Boolean>> systemPropertyBoolean(Class qualifier, String defaultValue);
static Function<String, Result<Integer>> systemPropertyInt(Class qualifier);
static Function<String, Result<Integer>> systemPropertyInt(Class qualifier, String defaultValue);
static Function<String, Result<Double>>  systemPropertyDouble(Class qualifier);
static Function<String, Result<Double>>  systemPropertyDouble(Class qualifier, String defaultValue);

static BiFunction<Class, String, String>  qualifiedParameter();
static BiFunction<Class, String, Boolean> hasSystemProperty();
static Function<String, Boolean>          hasSystemProperty(Class qualifier);

The Class qualifier is prepended to the property name to namespace your config โ€” e.g. for class com.acme.Db and key "port", the actual property looked up is com.acme.Db.port. This makes it harder for two unrelated modules to fight over the same global key.

class Db {}

int port = SystemProperties.systemPropertyInt(Db.class)
                           .apply("port")               // looks up com.example.Db.port
                           .getOrElse(() -> 5432);

StringFunctions

A large library (~86 public methods) of curried string operations โ€” many ported from Strman-Java. Selected highlights:

// Basic
Function<String, String>          collapseWhitespace();
Function<String, String>          base64Encode();
Function<String, String>          base64Decode();
Predicate<String>                 notEmpty();

// Searching
BiFunction<String, String, Boolean>            contains();
BiFunction<String, String, Boolean>            endsWith();
BiFunction<String, String, Boolean>            notStartsWith();
BiFunction<String, String[], Boolean>          containsAll();
BiFunction<String, String[], Boolean>          containsAny();
BiFunction<String, String, Long>               countSubStr();

// Building
BiFunction<String, String, String>             append();
BiFunction<String, Integer, String>            repeat();
TriFunction<String, String, Integer, String>   leftPad();
BiFunction<String, String[], String>           appendArray();
BiFunction<String, Collection<String>, String> appendCollection();

// Indexing
BiFunction<String, Integer, Result<String>>    at();   // bounds-safe

The full method list lives in the source.

  • Result<T> โ€” what every Converting / SystemProperties call hands back.
  • Transformations โ€” composition helpers that go well with these.