Functional programming is a trending topic these days and a lot of Java programmers are hot for the features that modern functional programming languages might offer.
Waiting for Java 8 and native closure support is a nice thing but for now we’re going to take a look at several Java frameworks that are trying to implement typical structures from those functional languages where possible using the capabilities of the Java language to emulate elements like higher-order-functions, closures, options and others …
lambdaj
Lambdaj is a framework that calls itself a library to “manipulate collections in a pseudo-functional and statically typed way” and it indeed offers a nice API to apply conversions, filtering, sorting, grouping, indexing, extractions and aggregations on java collections.
More detailed examples and documentation for lambdaj can be found on the project’s website.
Maven Dependency
We need to add the following one dependency to our pom.xml to work with lambdaj:
<dependency>
<groupId>com.googlecode.lambdaj</groupId>
<artifactId>lambdaj</artifactId>
<version>2.3.3</version>
</dependency>
Preparation
The following class will be used in several following examples to perform filtering, conversions, aggregations and other stuff with it ..
package com.hascode.sample;
import java.util.Date;
public class Book {
private final String title;
private final Date published;
private float price;
public Book(final String title, final Date published) {
this.title = title;
this.published = published;
}
public String getTitle() {
return title;
}
public Date getPublished() {
return published;
}
public float getPrice() {
return price;
}
public void setPrice(final float price) {
this.price = price;
}
}
Handling Collections like single Objects
In the following example we’re setting the price for each book in the collection using forEach and the normal setter.
package com.hascode.tutorial;
import static ch.lambdaj.Lambda.forEach;
import static ch.lambdaj.Lambda.joinFrom;
import static ch.lambdaj.Lambda.on;
import static ch.lambdaj.Lambda.sort;
import static java.util.Arrays.asList;
import java.util.Date;
import java.util.List;
public class LambdajExamples {
public static void main(final String... args) {
List<Book> books = asList(new Book("Some book", new Date(123)),
new Book("Another book", new Date(456)), new Book(
"I luv codin", new Date(789)));
// treating a collection like a single object
forEach(books).setPrice(10.0f); // sets the price on all objects
System.out.println(books.get(0).getPrice()); // output: 10.0
System.out.println(books.get(1).getPrice()); // output: 10.0
System.out.println(books.get(2).getPrice()); // output: 10.0
}
}
Sorting by Object’s Fields
We’re reusing the list of books from the example above. First we’re sorting the list on the book’s publication date in the second example we’re sorting the list on the title.
// sorting the books by publication date
List<Book> booksByDate = sort(books, on(Book.class).getPublished());
System.out.println(booksByDate.get(0).getTitle()); // "output: Some book"
System.out.println(booksByDate.get(1).getTitle()); // "output: Another book"
System.out.println(booksByDate.get(2).getTitle()); // "output: I luv coding"
// sorting the books by title
List<Book> booksByTitle = sort(books, on(Book.class).getTitle());
System.out.println(booksByTitle.get(0).getTitle()); // "output: Another book"
System.out.println(booksByTitle.get(1).getTitle()); // "output: I luv coding"
System.out.println(booksByTitle.get(2).getTitle()); // "output: Some book"
The same code in Scala could look like this one:
List(new Book("Some book", new Date(123)),
new Book("Another book", new Date(456)), new Book(
"I luv codin", new Date(789))).sort(_.title < _.title).foreach(b => println(b.title))
Aggregating Values into a List of Comma-Separated Values
We’re using the list of books from the first example again here and join the books titles into a string ..
// create a comma separated list of titles from the books collection
String titles = joinFrom(books).getTitle();
System.out.println(titles); // "Some book, Another book, I luv codin"
Searching by an Object’s Field
In the following example, we’re searching for a specific book’s title
// find books with title=Some book
List<Book> booksWithSpecifiedTitle = select(books,
having(on(Book.class).getTitle(), equalTo("Some book")));
System.out.println(booksWithSpecifiedTitle.size()); // output:1
System.out.println(booksWithSpecifiedTitle.get(0).getPrice()); // "output: 10.0"
Functionaljava
On the one hand, functional java seeks to improve using the Java programming language – on the other hand it serves as a platform to learn functional programming using a well known language: Java.
This library offers the following features as cited from the project’s website on functionaljava.org:
-
Fully operational Actors for parallel computations (fj.control.parallel) and layered abstractions such as parallel-map, map-reduce, parallel-zip.
-
A package (fj.data.fingertrees) providing 2-3 finger trees for a functional representation of persistent sequences supporting access to the ends in amortized O(1) time.
-
Type-safe heterogeneous list (fj.data.hlist) for lists of elements of differing types without sacrificing type-safety.
-
Monadic parser combinators for writing parsers by combining smaller parsers using composition.
-
Conversion of data types to/from standard Java types.
-
Immutable, in-memory singly linked list (fj.data.List).
-
Immutable lazy singly linked list (fj.data.Stream).
-
Array wrapper (fj.data.Array).
-
Optional value — type-safe null (fj.data.Option).
-
Disjoint union data type — compositional exception handling (fj.data.Either).
-
Monoid (fj.Monoid).
-
Functions with arity 1 to 8.
-
Products of 1 to 8.
-
Configurable equality and hash-code for HashMap and HashSet.
-
Natural number data type (fj.data.Natural).
-
Immutable set implementation using a red/black tree.
-
Immutable multi-way tree — aka rose tree (fj.data.Tree).
-
Immutable tree-map using a red/black tree implementation (fj.data.TreeMap).
-
Zipper implementations for streams and trees.
-
Automated specification-based testing framework (fj.test).
These are indeed a lot of features – in the following examples I am trying to demonstrate a few of them ..
Adding the library to a Project
We just need one Maven dependency here to be added to our pom.xml
<dependency>
<groupId>org.functionaljava</groupId>
<artifactId>functionaljava</artifactId>
<version>3.1</version>
</dependency>
Functions of different arity
Functionaljava offers generic classes to provide anonymous functions of different arities (from 1 to 8) – the last generic class type parameter is the return type the other parameters are mapped as function parameters.
package com.hascode.tutorial;
import static fj.data.Array.array;
import fj.Effect;
import fj.F;
import fj.F2;
public class DifferentArityFunctionsExample {
public static void main(final String[] args) {
F<String, Boolean> endsWithX = new F<String, Boolean>() {
@Override
public Boolean f(final String a) {
return a.endsWith("x");
}
};
F2<String, String, Boolean> stringsEqual = new F2<String, String, Boolean>() {
@Override
public Boolean f(final String a, final String b) {
return a.equals(b);
}
};
// output: "barx bazx"
array("foo", "barx", "moo", "bazx").filter(endsWithX).foreach(output);
}
static Effect<String> output = new Effect<String>() {
@Override
public void e(final String a) {
System.out.println(a);
}
};
}
The corresponding code in Scala could be something like this one
List("foo", "barx", "moo", "bazx").filter(_.endsWith("x")).foreach(println);
Array Filtering
In the following example we’re using a function to filter strings from a collection into a new collection.
import static fj.data.Array.array;
import fj.Effect;
import fj.F;
import fj.data.Array;
public class ArrayFilteringExample {
public static void main(final String[] args) {
final Array<String> a = array("This", "is", "an", "example");
final Array<String> b = a.filter(new F<String, Boolean>() {
@Override
public Boolean f(final String a) {
return a.matches(".*i.*");
}
});
b.foreach(new Effect<String>() {
@Override
public void e(final String a) {
System.out.println(a);
}
}); // output: This is
}
}
The counterpart in Scala:
List("This", "is", "an", "example").filter(_.matches(".*i.*")).foreach(println)
Applying a function to each element in a list
In the following example we’re manipulating an array of integers by multiplying each element in the list by 1 and sum the results.
package com.hascode.tutorial;
import static fj.data.Array.array;
import static fj.function.Integers.multiply;
import fj.Effect;
import fj.F;
public class FoldLeftExample {
public static void main(final String[] args) {
// multiplies each element in the array with 1 and adds the results
int result = array(1, 2, 3, 5).foldLeft(multiply, 1);
System.out.println(result); // 30
}
}
In the following example we’re using map and an anonymous function F to add 1 to each element in a list of integers and multiply the result by 2.
Finally we’re using another function, Effect to print the elements.
package com.hascode.tutorial;
import static fj.data.Array.array;
import static fj.function.Integers.multiply;
import fj.Effect;
import fj.F;
public class ApplyingFunctionPerListElementExample {
public static void main(final String[] args) {
// adds 1 to each element and multiplies the result by 2
// output: 4 6 8 12
array(1, 2, 3, 5).map(new F<Integer, Integer>() {
@Override
public Integer f(final Integer a) {
return (a + 1) * 2;
}
}).foreach(new Effect<Integer>() {
@Override
public void e(final Integer a) {
System.out.print(a + " ");
}
});
}
}
Either Example
The Either represents a value from a computation of one of two possible types mapped to the left and right value of the Either instance.
Often the left value represents an exception or error thrown during the computation and the right one the value if no error was thrown.
In the following example in the first execution a NumberFormatException is thrown and either.isLeft() returns true in the second example, no exception is thrown and we’re able to fetch the computation result using either.right().value().
package com.hascode.tutorial;
import fj.data.Either;
public class EitherExample {
public static void main(final String[] args) {
Either<Exception, Integer> result1 = parseInteger("123456h4");
System.out.println(result1.isLeft()); // true
System.out.println(result1.left().value().getClass()); // "class java.lang.NumberFormatException"
Either<Exception, Integer> result2 = parseInteger("123456");
System.out.println(result2.isLeft()); // false
System.out.println(result2.right().value()); // 123456
}
private static Either<Exception, Integer> parseInteger(final String string) {
try {
return Either.right(Integer.valueOf(string));
} catch (Exception e) {
return Either.left(e);
}
}
}
Option Example
An option encapsules the result of a computation and represents optional values. In Scala, instances of an Option are either an instance of Some or of None.
In the following example an integer is parsed from a given string .. in the first example, a NumberFormatException is thrown so option.isNone() returns true and option.isSome() returns false.
In the second example no exception is thrown and the opposite is the case – in addition we’re able to fetch the Integer using option.Some().
So what is the advantage of that? On the one hand, we don’t need to handle exceptions directly – on the other hand, to use an Option might give other programmers reading your code a hint that the performed computation might not yield a result and it is necessary to handle that.
package com.hascode.tutorial;
import fj.data.Option;
public class OptionExample {
public static void main(final String[] args) {
Option<Integer> result1 = parseInteger("1234G46");
System.out.println(String.format("isNone: %s / isSome: %s",
result1.isNone(), result1.isSome())); // "isNone: true / isSome: false"
Option<Integer> result2 = parseInteger("1234");
System.out.println(String.format("isNone: %s / isSome: %s",
result2.isNone(), result2.isSome())); // "isNone: false / isSome: true"
System.out.println(result2.some()); // 1234
}
private static Option<Integer> parseInteger(final String string) {
try {
return Option.some(Integer.valueOf(string));
} catch (Exception e) {
return Option.none();
}
}
}
There are many other interesting features present in this library so if you’re interested please take a look at the detailed information on the project’s website.
Guava
Guava is the modern version of commons-collections (also described in this article) and offers some helpful APIs for handling collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O and other stuff.
For a full list of its features please take a look at the project’s website.
Adding Guava to a Project
One Maven dependency needed – here it is:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>12.0</version>
</dependency>
Predicate Example
In the first example, we’re using a Predicate to filter a list of books for books with a publication date >= 2000, in the second example by their author.
package com.hascode.tutorial;
import static com.google.common.collect.Lists.newArrayList;
import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
public class GuavaPredicates {
public static void main(final String[] args) {
List<Book> books = newArrayList(new Book("Some book", "Arnold Author",
1998), new Book("Programmers are weird", "Some author", 2011),
new Book("Another book", "Another author", 2012), new Book(
"Ye ole book", "Ye authorr", 1711), new Book(
"Some book - second edition", "Arnold Author", 2010));
Predicate<Book> newerThanYear2000 = new Predicate<GuavaPredicates.Book>() {
public boolean apply(final Book book) {
return book.getYearPublished() >= 2000;
}
};
Predicate<Book> byAuthorArnold = new Predicate<GuavaPredicates.Book>() {
public boolean apply(final Book book) {
return book.getAuthor().equals("Arnold Author");
}
};
System.out.println("books published in year 2000 and later");
System.out.println(Iterables.filter(books, newerThanYear2000)
.toString());
System.out.println("books by author=Arnold Author");
System.out.println(Iterables.filter(books, byAuthorArnold).toString());
}
static class Book {
final String title;
final String author;
final int yearPublished;
public Book(final String title, final String author,
final int yearPublished) {
this.title = title;
this.author = author;
this.yearPublished = yearPublished;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public int getYearPublished() {
return yearPublished;
}
@Override
public String toString() {
return "Book [title=" + title + ", author=" + author
+ ", yearPublished=" + yearPublished + "]";
}
}
}
Function / Transformer
In the following example we’re defining a generic function to transform a collection of books into a collection of strings based on the books titles
Function<Book, String> titleTransformer = new Function<GuavaExamples.Book, String>() {
public String apply(final Book book) {
return "X " + book.getTitle();
}
};
// outputs:
// "[X Some book, X Programmers are weird, X Another book, X Ye ole book, X Some book - second edition]"
System.out.println(Iterables.transform(books, titleTransformer));
Optional
Guava offers a structure to signal that the result of a computation might yield no result – Optional.
In the following example the first computation throws a NumberFormatException and no result is possible – in the second call we’re able to test for valid computation and return the value from the operation. As you might have noticed this approach is similar to the Option of the functionaljava example.
Optional<Integer> computed1 = computeIntegerFrom("1234zzx");
System.out.println(computed1.isPresent()); // false
Optional<Integer> computed2 = computeIntegerFrom("12345");
System.out.println(computed2.isPresent()); // true
System.out.println(computed2.get()); // 12345
[..]
private static Optional<Integer> computeIntegerFrom(
final String numberAsString) {
try {
Integer i = Integer.valueOf(numberAsString);
return Optional.of(i);
} catch (Exception e) {
}
return Optional.absent();
};
Apache Commons Collection
Though commons collections has no support for generics it is still used or referenced in many projects. There are three features that I’d like to demonstrate here:
-
Closures: Are simple functions that allows us to get a reference to each object in the collection and alter the object
-
Transformers: Enables us to transform data from one format into another
-
Predicates: Similar to the Guava example above the allow us to test each element of a collection to filter a collection
If you’re used to commons collections that much that you do not want to switch to Guava for some of the features please take a look at the collections-generics project on GitHub – it’s an implementation of commons-collections with generics support.
Maven Dependencies
We just need one dependency to integrate commons-collections into our project..
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
Predicates to filter Collections
The following example filters a list of books by their title so that all books with a title that does not contain the string book are filtered from the collection. As you might have noticed – in contrast to Guava without generics we’re forced to work with an object in our predicate.
package com.hascode.tutorial;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.iterators.FilterIterator;
public class CommonsCollectionExample {
public static void main(final String[] args) {
List<Book> books = new ArrayList<Book>();
books.add(new Book("Some book", new Date(123)));
books.add(new Book("Another book", new Date(456)));
books.add(new Book("I luv codin", new Date(789)));
Predicate titlePredicate = new Predicate() {
public boolean evaluate(final Object obj) {
return ((Book) obj).getTitle().matches(".*book$");
}
};
@SuppressWarnings("unchecked")
Iterator<Book> booksIterator = new FilterIterator(books.iterator(),
titlePredicate);
while (booksIterator.hasNext()) {
System.out.println(booksIterator.next().getTitle());
}
// output:
// Some book
// Another book
}
}
Closures
We’re recycling the book list from the example above and we’re applying a closure to each element of the collection that print’s the books title:
Closure closure = new Closure() {
public void execute(final Object obj) {
Book book = (Book) obj;
System.out.println("the book's title is: " + book.getTitle());
}
};
CollectionUtils.forAllDo(books, closure);
// the book's title is: Some book
// the book's title is: Another book
// the book's title is: I luv codin
Transformer
First of all we’re recycling the list of books and the title-printing-closure from the examples above – second we’re applying a transformer on the collection of books to create a new collection of books with a modified title..
Transformer transformer = new Transformer() {
public Object transform(final Object obj) {
Book book = (Book) obj;
return new Book("X " + book.getTitle(), book.getPublished());
}
};
Collection<Book> transformedBooks = CollectionUtils.collect(books,
transformer);
CollectionUtils.forAllDo(transformedBooks, closure);
// the book's title is: X Some book
// the book's title is: X Another book
// the book's title is: X I luv codin
Funcito
Funcito is a shiny new library that simplifies access to our favourite functional java libraries like functionaljava, guava or jedi – and allows us to use the structures of these frameworks with less writing ;)
The following libraries and features are currently supported:
-
Google Guava Function and Predicate interfaces
-
Functional Java the F (function) interface
-
Jedi-core Functor and Filter interfaces
-
Play! Framework 2 F.Function interface
-
Collection-generic Transformer and Predicate interfaces
I’ll be covering only a few examples here but if you’re interested, please take a deeper look at the Funcito project website.
Maven Dependencies
One dependency needed .. simply add this one to your pom.xml
<dependency>
<groupId>com.googlecode.funcito</groupId>
<artifactId>funcito</artifactId>
<version>1.2.0</version>
</dependency>
Guava Predicates in short
The first examples shows how to create Guava predicates with a shorter syntax
package com.hascode.tutorial;
import static com.google.common.collect.Lists.newArrayList;
import static org.funcito.FuncitoGuava.callsTo;
import static org.funcito.FuncitoGuava.predicateFor;
import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
public class FuncitoExample1 {
public static void main(final String[] args) {
List<User> users = newArrayList(new User("Bob", false), new User("Tim",
true), new User("Suz", true), new User("Charlize", false),
new User("Allan", false), new User("Steve", true));
Predicate<User> activeUsers = predicateFor(callsTo(User.class)
.isActive());
System.out.println("active users are:");
System.out.println(Iterables.filter(users, activeUsers).toString());
}
private static class User {
private final String name;
private final boolean active;
public User(final String name, final boolean active) {
this.name = name;
this.active = active;
}
public String getName() {
return name;
}
public boolean isActive() {
return active;
}
@Override
public String toString() {
return "User [name=" + name + ", active=" + active + "]";
}
}
}
This produces the following output:
active users are:
[User [name=Tim, active=true], User [name=Suz, active=true], User [name=Steve, active=true]]
Guava Functions and Transformers
In the following example we’re defining a function handling the users’ names and use this function to transform the list of users into a list of strings (the users’ names).
package com.hascode.tutorial;
import static com.google.common.collect.Lists.newArrayList;
import static org.funcito.Funcito.callsTo;
import static org.funcito.FuncitoGuava.functionFor;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
public class FuncitoExample2 {
public static void main(final String[] args) {
List<User> users = newArrayList(new User("Bob", false), new User("Tim",
true), new User("Suz", true), new User("Charlize", false),
new User("Allan", false), new User("Steve", true));
System.out.println("user names:");
Function<User, String> namesFunc = functionFor(callsTo(User.class)
.getName());
List<String> userNames = Lists.transform(users, namesFunc);
System.out.println(userNames);
}
private static class User {
private final String name;
private final boolean active;
public User(final String name, final boolean active) {
this.name = name;
this.active = active;
}
public String getName() {
return name;
}
public boolean isActive() {
return active;
}
@Override
public String toString() {
return "User [name=" + name + ", active=" + active + "]";
}
}
}
Running the example above should print the following result
user names:
[Bob, Tim, Suz, Charlize, Allan, Steve]
Pure Java
Having shown a lot of libraries here are some examples in pure Java..
In the first example, a Runnable is used as a sort of higher order function ..
new Thread(new Runnable() {
public void run() {
System.out.println("i am enclosed ;)");
}
}).start();
Another common examples is the Comparator interface that allows to sort collections ..
List<String> names = new ArrayList<String>();
names.add("Tim");
names.add("Bart");
names.add("Zaphod");
Collections.sort(names, new Comparator<String>() {
public int compare(final String s1, final String s2) {
return s2.compareTo(s1);
}
});
// output: [Zaphod, Tim, Bart]
System.out.println(names.toString());
Other Libraries
There is a bunch of other libraries out there some of them promising some others are not active developed any more ..
-
commons-functor (alpha is attached to the tutorial’ sources)
Tutorial Sources
I have put the source from this tutorial on my GitHub repository – download it there or check it out using Git:
git clone https://github.com/hascode/functional-java-examples.git