Skip to content

ToToTec/de.tototec.utils.functional

Repository files navigation

Functional Utils

Introduction

This project consists of some useful helper classes and interfaces, which help to write more functional Java code.

The classes are:

  • FList - contains static methods returning mostly java.util.List s and accepting Iterable s and arrays, like map, flatMap, filter, …​

  • F0, F1, F2, F3, F4 - Interfaces representing a function with n args where n is given by the interface name suffix

  • CheckedF0, CheckedF1 - Interfaces representing a function with n args throwing an Exception where n is given by the interface name suffix

  • Procedure0, Procedure1, Procedure2, Procedure3, Procedure4 - Interfaces representing a procedure with n args where n is given by the interface name suffix

  • Optional - An immutable class representing an optional value

  • Either - An immutable class representing either one of two values

  • Tuple2, Tuple3, …​ - Classes representing tuples with n args where n is given by the name

  • Try - An experimental wrapper around computations, that may throw exceptions

  • CanEqualsSupport - An helper class to produce proper equals and hashCode as well as canEqual methods.

All those classes and interfaces can be used with Java 8 and above. Releases up until 2.3.0 also supported Java 5+. Although by their use, your code will not get more compact, but hopefully less errorprone.

There are a lot of more sophisticated functional libraries for Java8+ around, but they all cannot be used with older Java versions. Therefore, the historical aim of this library was to stay Java5+ compatible.

Of course, programming with lambda expressions and anonymous classes in older Java versions isn’t much fun. Please read the Java8 sections below, to learn how to code in Java8 source level but compile and convert Bytecode to older Java versions transparently.

Examples

Example for Java 8
import java.util.*;
import de.tototec.utils.functional.*;
import static de.tototec.utils.functional.FList.*;

List<String> names = Arrays.asList("Alice", "Bob", "Carlie", "Dylan");
// --> [Alice, Bob, Carlie, Dylan]

// Filtering
List<String> namesWithE_ = filter(names, name -> name.contains("e"));
// --> [Alice, Carlie]

// Apply a function to all elements
List<String> namesUppercase_ = map(names, name -> name.toUppercase());
// --> [ALICE, BOB, CARLIE, DYLAN]
Example for Java 7 and before (only work until release 2.3.0)
import java.util.*;
import de.tototec.utils.functional.*;
import static de.tototec.utils.functional.FList.*;

List<String> names = Arrays.asList("Alice", "Bob", "Carlie", "Dylan");
// --> [Alice, Bob, Carlie, Dylan]

// Filtering
List<String> namesWithE = filter(names, new F1<String, Boolean>() {
  public Boolean apply(String name) {
    return name.contains("e");
  }
});
// --> [Alice, Carlie]

// Apply a function to all elements
List<String> namesUppercase = map(names, new F1<String, String>() {
  public String apply(String name) {
    return name.toUppercase();
  }
});
// --> [ALICE, BOB, CARLIE, DYLAN]

Download

Functional Utils is available from Maven central repository.

Maven
<dependency>
  <groupId>de.tototec</groupId>
  <artifactId>de.tototec.utils.functional</artifactId>
  <version>2.3.0</version>
</dependency>
Polyglot Maven Scala / SBT
"de.tototec" % "de.tototec.utils.functional" % "2.3.0"
ivy"de.tototec:de.tototec.utils.functional:2.3.0"

Documentation

Use with Java 8 Lambdas

Writing functional code can be much more pleasant if Java 8 Lambda expressions can be used. The function and procedure interfaces all fulfil the requirements for functional interfaces and can be thus implicitly inferred when lambda expressions are used.

Use of Java 8 Lambdas for earlier Java Runtimes

Please refer to an older version of this Readme (e.g. 2.3.0) for this information.

Changelog

main

  • Build with Mill, drop Maven support

  • Drop support for Java versions before Java 8

2.3.0 - 2021-11-23

  • Added more functions to Either and make it right-biased

2.2.0 - 2021-11-04

  • CanEqualsSupport: Added support to give canEqual call as function

2.1.1 - 2021-09-06

  • Added @SafeVarargs annotation to CanEqualsSupport

2.1.0 - 2019-11-28

  • Added CanEqualsSupport to create proper equals and hashCode methods.

2.0.1 - 2019-04-11

  • Fixed a logic error in Try.failure

2.0.0 - 2018-03-17

  • Added FList.append and FList.prepend

  • Added FList.toList

  • Added Optional.of as a preferred alternative to Optional.lift

  • Added Procedure4

  • Added more FList.toHashMap variants

  • Deprecated Optional.lift in favour of Optional.of

  • Changed signature of Optional.orElseF

  • Made classes Either and Try final

1.0.0 - 2017-12-14

  • Made some classes and methods final

  • Changed from Default JavaDoc processor to Asciidoclet processor

  • Migrated Maven build file (pom.xml) to Polyglot Scala Extension (pom.scala)

  • Added extractor methods Tuple2.extractA and Tuple2.extractB

  • Removed deprecated Optional.getOrElse override for F0

  • Changed thrown exceptions from NullPointerException to NoSuchElementException, e.g. in Optional.get or Either.right

  • Added Tuple5

  • Added experimental Try

  • Added CheckedF0 and CheckedF1 as throwing couterpart of F0 and F1

  • Added Either.leftTry and Either.rightTry

  • Added FList.drop

  • Added FList.take

0.7.0 - 2016-06-01

  • Fixed faulty FList.distict method

  • Added no-op impls for Procedure interfaces

  • Improved / fixed signature of FList.flatten

  • Changed toString of Optional

  • Added FList.headOption

  • Added FList.tail

  • Added Optional.getOrElseF

  • Added Optional.orElse and Optional.orElseF

  • Added FList.filterNotNull

  • Added FList.concat

0.6.0 - 2015-11-11

  • Changed order of type parameters in methods of FList

  • Added Optional.getOrElse

  • Added Optional.foreach

  • Added FList.contains

  • Added FList.containsAll

  • Added FList.toHashMap

0.5.0 - 2014-11-14

  • Initial Release after migration to GitHub