Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

More-or-less functional util library for Java.

Code generation ( is highly recommended since it provides first-class-functions in regular java code, thus greatly lessening the pain of using functional constructs.

Build and test and package


Add the following file (or the latest version) to classpath:

You might also want to use Eclipse favorites (any similar thing in Idea?) so that you don't jave to write so many import clauses. Add the following types/functions to Eclipse Preferences -> Java -> Editor -> Content Assist -> Favorites:


Just a few examples of using these utils.

fi.solita.utils.functional.lens.Builder and fi.solita.utils.functional.lens.Lens

class Department {
    final String name;
    final List<Employee> employees;

    public static final Builder<Department> builder = Builder.of(Department_.$Fields(), Department_.$);
    public Department(String name, List<Employee> employees) { = name;
        this.employees = employees;
    public Department(String name) { = name;
        this.employees = Collections.emptyList();

class Employee {
    final String name;
    final Option<Integer> salary;
    final Department department;
    public static final Builder<Employee> builder = Builder.of(Employee_.$Fields(), Employee_.$);

    public Employee(String name, Option<Integer> salary, Department department) { = name;
        this.salary = salary;
        this.department = department;

/** Generated in practice by meta-utils */
class Department_ {
    public static final Tuple2<Apply<Department,String>,Apply<Department,List<Employee>>> $Fields() {
        return Tuple.of(name, employees);
    public static final Function2<String, List<Employee>, Department> $ = new Function2<String, List<Employee>, Department>() {
        public Department apply(String t, List<Employee> e) {
            return new Department(t, e);
    public static final Apply<Department, String> name = new Apply<Department, String>() {
        public String apply(Department t) {
    public static final Apply<Department, List<Employee>> employees = new Apply<Department, List<Employee>>() {
        public List<Employee> apply(Department t) {
            return t.employees;

/** Generated in practice by meta-utils */
class Employee_ {
    public static final Tuple3<Apply<Employee,String>,Apply<Employee,Option<Integer>>,Apply<Employee,Department>> $Fields() {
        return Tuple.of(name, salary, department);
    public static final Function3<String, Option<Integer>, Department, Employee> $ = new Function3<String,Option<Integer>,Department,Employee>() {
        public Employee apply(String t1, Option<Integer> t2, Department t3) {
            return new Employee(t1, t2, t3);
    public static final Apply<Employee, String> name = new Apply<Employee, String>() {
        public String apply(Employee t) {
    public static final Apply<Employee, Option<Integer>> salary = new Apply<Employee, Option<Integer>>() {
        public Option<Integer> apply(Employee t) {
            return t.salary;
        public Member getMember() {
            try {
                return Employee.class.getDeclaredField("salary");
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
    public static final Apply<Employee, Department> department = new Apply<Employee, Department>() {
        public Department apply(Employee t) {
            return t.department;

public class BuilderAndLensExamples {

    public void builder() {
        Employee employee = Builder.of(Employee_.$Fields(), Employee_.$)
            .with(, "John")
            .with(Employee_.department, new Department("Sales"))
        assertEquals(None(), employee.salary);
    public void lens() {
        Employee employee = new Employee("John", Some(42), new Department("Sales"));
        Lens<Employee,String> name_ = Lens.of(, Employee.builder);

        assertEquals("John", name_.get(employee));

        Employee newEmployee = name_.set(employee, "Jane");

    public void deepLens() {
        Employee employee = new Employee("John", Some(42), new Department("Sales"));

        Lens<Employee, Department> employeeDepartment_ = Lens.of(Employee_.department, Employee.builder);
        Lens<Department, String> departmentName_ = Lens.of(, Department.builder);
        Lens<Employee, String> employeeDepartmentName_ = employeeDepartment_.andThen(departmentName_);

        assertEquals("Sales", employeeDepartmentName_.get(employee));

        Employee newEmployee = employeeDepartmentName_.set(employee, "IT");
    public void listLens() {
        Department department = new Department("Sales", newList(new Employee("John", Some(42), new Department("IT"))));

        Lens<Department, List<Employee>> departmentEmployees_ = Lens.of(Department_.employees, Department.builder);
        Lens<Employee, Option<Integer>> employeeSalary_ = Lens.of(Employee_.salary, Employee.builder);

        assertEquals(newSet(42), newSet(flatMap(Employee_.salary, departmentEmployees_.get(department))));

        Setter<Department,Option<Integer>> departmentSalaries_ = Lens.eachList(departmentEmployees_, employeeSalary_);
        assertEquals(newSet(69), newSet(flatMap(Employee_.salary, departmentSalaries_.set(department, Some(69)).employees)));
        Lens<Department, String> departmentName_ = Lens.of(, Department.builder);
        Lens<Employee, Department> employeeDepartment_ = Lens.of(Employee_.department, Employee.builder);
        Setter<Department,Department> departmentEmployeeDepartments_ = Lens.eachList(departmentEmployees_, employeeDepartment_);
        Setter<Department,String> departmentEmployeeDepartmentsName_ = departmentEmployeeDepartments_.andThen(departmentName_);
        assertEquals(newSet("IT2"), newSet(map(, map(Employee_.department, departmentEmployeeDepartmentsName_.set(department, "IT2").employees))));


List<Integer> emptyList = newList();
Set<String> emptySet = newSet();
Map<Long, Integer> emptyMap = newMap();

int[] primitiveArray = new int[]{1, 2, 3};
List<Integer> listFromPrimitives = newList(primitiveArray);
Set<Integer> setFromPrimitives = newSet(primitiveArray);

Iterable<Integer> iterable = newList(1, 2, 3);
List<Integer> listFromIterable = newList(iterable);
Set<Integer> setFromIterable = newSet(iterable);

List<? extends Map.Entry<String, Integer>> entries = newList(Pair.of("foo", 1), Pair.of("bar", 2));
Map<String, Integer> mapFromIterableEntries = newMap(entries);
Map<String, Integer> mapFromEntries = newMap(Pair.of("foo", 1), Pair.of("bar", 2));

Character[] arrayFromPrimitives = newArray('a', 'b', 'c');
char[] primitiveArrayFromObjectArray = newArray(arrayFromPrimitives);
Character[] objectArrayFromPrimitiveArray = newArray(primitiveArrayFromObjectArray);

Iterable<Character> charSequenceToIterable = it("foo");


Option<String> optionContainingFoo = Some("foo");
Option<String> emptyOption = None();

Option<String> valueResultsInSome = Option.of("foo");
Option<Object> nullResultsInNone = Option.of(null);

String string = optionContainingFoo.get();
try { 
} catch (UnsupportedOperationException e) {}

String foo = optionContainingFoo.getOrElse("bar");
String bar = emptyOption.getOrElse("bar");

boolean someIsDefined = Some("foo").isDefined();
boolean noneIsNotDefined = None().isDefined();

for (String str: optionContainingFoo) {
    // executed once

for (String str: emptyOption) {
    // never executed


static class Employee {
	public int salary;
	public Option<String> name;

// ...

Ordering<Comparable<?>> byNaturalOrdering = Compare.byNatural();
Ordering<Employee> byComparable =;
Ordering<Employee> byExplicitComparator =, Ordering.Natural());

Ordering<_1<? extends Comparable<?>>> by_1 = Compare.by_1;

List<Tuple2<String, Employee>> listOfTuples = newList();
sort(by_1, listOfTuples);
// Employee does not implement comparable, but we can first map to _2 and then to salary
sort(<Employee>_2().andThen(salary)), listOfTuples);

// sorted by the contents of an iterable
sort(Compare.<String>byIterable(), Collections.<List<String>>newList());

// sorted by the contents of an Option
sort(Compare.<String>byOption(), Collections.<Option<String>>newList());

// sorted by a function to an Option
sort(Compare.byOption(name), Collections.<Employee>newList());

// and the same with explicit comparators
sort(Compare.byIterable(, Collections.<List<Employee>>newList());
sort(Compare.byOption(, Collections.<Option<Employee>>newList());
sort(Compare.byOption(name, Ordering.Natural()), Collections.<Employee>newList());


Tuple1<String> tuple1 = Tuple.of("foo");
Map.Entry<String,String> tuple2extendsMapEntry = Tuple.of("a", "b");
Tuple2<String,String> pairExtendsTuple2 = Pair.of("left", "right");
// ... until Tuple22

// a List of common supertype
List<String> strings = Tuple.asList(Tuple.of("str1", "str2"));
List<? extends Object> objects = Tuple.asList(Tuple.of(42, "foo"));
List<? extends Number> numbers = Tuple.asList(Tuple.of(42, 42l));

Object[] values = Tuple.of("str").toArray();

Tuple3<Integer,String,Boolean> tuple = Tuple.of(42, "b", true);
String valueByFieldAccess = tuple._2;

Pair<Integer,String> pair = Pair.of(42, "right");
String right = pair.right;
int left = pair.left;

Tuple2<String, Integer> appendedRight = Tuple.of("str").append(42);
Tuple3<Boolean, String, Integer> prependedLeft = appendedRight.prepend(true);

Tuple4<Integer, String, Boolean, Object> bigtuple = Tuple.of(42, "str", true, new Object());
Tuple2<Integer,String> prefix2 = bigtuple.take2();
Tuple3<Integer, String, Boolean> prefix3 = bigtuple.take3();

List<Pair<String,Integer>> listOfTuples = newList();
Iterable<Integer> projection = map(listOfTuples, Transformers.<Integer>_2());


static Transformer<String,Integer> length = new Transformer<String,Integer>() {
    public Integer transform(String source) {
        return source.length();

static Function2<Integer,Integer,Integer> mod = new Function2<Integer,Integer,Integer>() {
    public Integer apply(Integer modulus, Integer i) {
        return i % modulus;


// Apply<T,R> is a function from T to R
Apply<String,Integer> f = length;

// Function0 ia a 0-arg function, Function1 1-arg, Function2 2-arg, etc.
Function0<Integer> zeroArg = Function.of(42);
Function1<String,Integer> oneArg = length;
Function2<Integer, Integer, Integer> twoArg = mod;

int applied = length.apply("foo");
Iterable<Integer> mappedOverFunction = map(f, newList("a", "aa"));

Function0<Integer> partiallyApplied = length.ap("foo");
int result = partiallyApplied.apply();
Function1<Integer, Integer> modulo42 = mod.ap(42);

Function1<Integer, Integer> partiallyApplyFirstParam = mod.apply(42, _);
Function1<Integer, Integer> partiallyApplySecondParam = mod.apply(_, 84);
// a function can also be split to two functions, dividing some params
// to the first one and others to the second one:
Function1<Integer, Function1<Integer, Integer>> split = mod.apply(__, _);

// function composition, one way or the other
Function1<String, String> func =;
Function1<String, Integer> composed = func.andThen(length);
Function1<String, Integer> composed2 = length.compose(func);

// multi-param function can be views as a 1-arg function of a Tuple:
Function2<Integer,Integer,Integer> m = mod;
Function1<Tuple2<Integer,Integer>,Integer> tuppled = m.tuppled();

Function2<Integer,Integer,Integer> twoArgFunction = mod;
Function1<Integer,Function1<Integer,Integer>> curried = twoArgFunction.curried();


static class Distance implements SemiGroup<Distance> {
	public final int meters;
	public Distance(int meters) {
		this.meters = meters;
	public Distance apply(final Tuple2<Distance, Distance> t) {
		return new Distance(t._1.meters + t._2.meters);


List<Long> longs = newList(1l, 2l);

// Longs (if assumed unbounded), Booleans and Strings are monoids,
// but they do not have "default instances of Monoid typeclass" so we
// must give one as a parameter.
long three = reduce(Monoids.longSum, longs);
long two = reduce(Monoids.longProduct, longs);
boolean notTrue = reduce(Monoids.booleanConjunction, newList(true, false));
String foobar = reduce(Monoids.stringConcat, newList("foo", "bar"));

// For classes having a default (SemiGroup) instance,
// no parameter is needed.
List<Distance> distances = newList(new Distance(1), new Distance(2));
Option<Distance> reduced = reduce(distances);

Map<String, Long> first = newMap();
Map<String, Long> second = newMap();
Map<String, Long> valuesSummed = reduce(Monoids.<String,Long>mapCombine(SemiGroups.longSum), newList(first, second));


for (Integer m: Match.instance(Integer.class, (Object)42)) {
	// executed only if object is an Integer 

for (Integer m: Match.singleton(newList(1))) {
	// executed only if the given iterable contains exactly one item

for (Pair<Integer, Integer> m: Match.pair(newList(1,2))) {
	// executed only if the given iterable contains exactly two items

for (Pair<Integer,Integer> m: Match.iterable(1, null, newList(1,2))) {
	// executed only if the iterable (last parameter) contains exactly as many
	// elements as given as previous parameters, and all non-null values
	// are equal to the corresponding element in the iterable.
	// So, you can use nulls to mean "this element can be anything"


// head
int head = head(someIterableOrArray);
assertEquals(1, head);

// headOption
Option<Integer> headOption = headOption(someIterableOrArray);
assertEquals(Some(1), headOption);
assertEquals(None(), headOption(emptyList()));

// last
int last = last(someIterableOrArray);
assertEquals(3, last);

// lastOption
Option<Integer> lastOption = lastOption(someIterableOrArray);
assertEquals(Some(3), lastOption);
assertEquals(None(), lastOption(emptyList()));

// tail
Iterable<Integer> tail = tail(someIterableOrArray);
assertEquals(newList(2,3), newList(tail));

// init
Iterable<Integer> init = init(someIterableOrArray);
assertEquals(newList(1,2), newList(init));

// take
Iterable<Integer> take = take(2, someIterableOrArray);
assertEquals(newList(1,2), newList(take));

// takeWhile
Iterable<Integer> takeWhile = takeWhile(odd, someIterableOrArray);
assertEquals(newList(1), newList(takeWhile));

// drop
Iterable<Integer> drop = drop(1, someIterableOrArray);
assertEquals(newList(2,3), newList(drop));

// dropWhile
Iterable<Integer> dropWhile = dropWhile(odd, someIterableOrArray);
assertEquals(newList(2,3), newList(dropWhile));

// span
Pair<Iterable<Integer>, Iterable<Integer>> span = span(odd, someIterableOrArray);
assertEquals(Pair.of(newList(1),         newList(2,3)),
             Pair.of(newList(span.left), newList(span.right)));

// isEmpty
boolean isEmpty = isEmpty(someIterableOrArray);
assertEquals(false, isEmpty);

// containment
boolean contains = contains(1, someIterableOrArray);
assertEquals(true, contains);

// size
long size = size(someIterableOrArray);
assertEquals(3l, size);

// cons
Iterable<Integer> cons = cons(0, someIterableOrArray);
assertEquals(newList(0,1,2,3), newList(cons));

// concat
Iterable<Integer> concat = concat(someIterableOrArray, someIterableOrArray);
assertEquals(newList(1,2,3,1,2,3), newList(concat));

// find
Option<Integer> find = find(even, someIterableOrArray);
Option<String> findFromMap = find(42, someMap);
assertEquals(Some(2), find);
assertEquals(Some("foo"), findFromMap);
assertEquals(None(), find(even, Collections.<Integer>emptyList()));

// filter
Iterable<Integer> filter = filter(odd, someIterableOrArray);
Map<Integer, String> filterFromMap = filter(evenKey, someMap);
assertEquals(newList(1,3), newList(filter));
assertEquals(newMap(Pair.of(42, "foo")), filterFromMap);

// exists
boolean exists = exists(even, someIterableOrArray);
assertEquals(true, exists);

// forall
boolean forall = forall(even, someIterableOrArray);
assertEquals(false, forall);

// foreach
foreach(someProcedure, someIterableOrArray);

// map
Iterable<Integer> map = map(negateInt, someIterableOrArray);
Map<Integer, String> mapOfMap = map(Function.<Map.Entry<Integer, String>>id(), someMap);
Iterable<Pair<Integer, Integer>> mapMultiple = map(negateInt, negateInt.andThen(negateInt), someIterableOrArray);
assertEquals(newList(-1,-2,-3), newList(map));
assertEquals(newMap(Pair.of(42, "foo")), mapOfMap);
assertEquals(newList(Pair.of(-1,1), Pair.of(-2,2), Pair.of(-3,3)), newList(mapMultiple));

// flatMap
Iterable<Integer> flatMap = flatMap(repeatTwice, someIterableOrArray);
assertEquals(newList(1,1,2,2,3,3), newList(flatMap));

// flatten
Iterable<Integer> flatten = flatten(map(repeatTwice, someIterableOrArray));
Iterable<Integer> flattenArrays = flatten(new Integer[][]{new Integer[]{1}, new Integer[]{2}});
assertEquals(newList(1,1,2,2,3,3), newList(flatten));
assertEquals(newList(1,2), newList(flattenArrays));

// fold
Option<Integer> fold = fold(SemiGroups.intSum, someIterableOrArray);
String foldFromZero = fold("->", SemiGroups.stringConcat, map(Transformers.toString, someIterableOrArray));
assertEquals(Some(6), fold);
assertEquals("->123", foldFromZero);

// reduce
long reduce = reduce(Monoids.longSum, map(Transformers.int2long, someIterableOrArray));
assertEquals(6l, reduce);

// union
Set<Integer> union = union(newSet(1,2), newSet(2,3));
assertEquals(newSet(1,2,3), union);

// intersection
Set<Integer> intersection = intersection(newSet(1,2), newSet(2,3));
assertEquals(newSet(2), intersection);

// subtract
Iterable<Integer> subtract = subtract(someIterableOrArray, newList(2));
assertEquals(newList(1,3), newList(subtract));

// min
Option<Integer> min = min(someIterableOrArray);
assertEquals(Some(1), min);
assertEquals(None(), min(Collections.<Integer>emptyList()));

// max
Option<Integer> max = max(someIterableOrArray);
assertEquals(Some(3), max);
assertEquals(None(), max(Collections.<Integer>emptyList()));

// sum
long sum = sum(1,2,3);
assertEquals(6l, sum);

// product
long product = product(1,2,3);
assertEquals(6l, product);

// sort
Iterable<Integer> sort = sort(someIterableOrArray);
Iterable<Integer> sortBy = sort(Compare.byNatural().reverse(), someIterableOrArray);
assertEquals(newList(1,2,3), newList(sort));
assertEquals(newList(3,2,1), newList(sortBy));

// reverse
// repeat
// range
// sequence
// distinct

// zip
// zipWithIndex
// transpose
// groupBy
// grouped

// mkString
// unlines

Word of warning

This package comes with no warranty what-so-ever. It's higly experimental, might contain loads of bugs and needs more testing. Packages and classes may get renamed or moved, and things may suddenly break. Use at your own risk!

Bug reports, feature requests and opinionated recommendations are highly welcome ;)


Copyright © Solita Oy

Distributed under the MIT License.


More-or-less functional util library for Java.