Table of Contents
Note: this chapter gives a brief overview of FunctionalJ. More detailed information is given in the later chapters of this document, starting with Chapter 4, Defining functions.
FunctionalJ is a library for functional programming in the Java language.
Simply put, within FunctionalJ, a function accepts 0 or more parameters, performs some computation, and returns a result.

This is very much like a constructor or a method, except that it is represented by a function object. This makes it easier to use functions in more ways than ordinary constructors or methods.
Starting with version 0.8, FunctionalJ is available not only in a JDK 1.4 version but also a JDK 1.5 version that uses type parameters and other JDK 1.5 features.
While Java is my favorite programming language, I discovered some interesting functional programming concepts when I learned the pure functional programming language Haskell (http://www.haskell.org). I still find object-oriented programming to be an excellent approach to developing code; in fact, my goal is to combine both by using functions as objects. Sometimes, using functional programming constructs can really make your code more practical.
FunctionalJ makes it easy to use these functional programming patterns in the Java language.
FunctionalJ also contains mechanisms for making the use of reflection easier. Sometimes you want to determine which method to invoke dynamically at runtime, which calls for reflection. The standard JDK mechanisms for using reflection are fairly verbose; FunctionalJ contains a dynamic reflection mechanism that is more concise. A standard reflection mechanism is also provided because it can, in some situations, have better performance.
Certain utility methods were written in the course of developing the library, and were made public in utility classes since they seemed to be convenient for general use.
Finally, my goal with FunctionalJ is to provide a library that is
practical. For example, the only exception that is thrown in the
library is an unchecked exception, so that you have the option of handling it or not.
Also, I did my best to handle null values without
throwing a NullPointerException, and to always
return non-null values, to eliminate as many checks
for nulls in client code. Of course, where a
null value is unacceptable, an exception is still
thrown.
Note: the examples in this section use reflection, but you do not have to use reflection in order to use FunctionalJ. You can also define functions by implementing an interface or subclassing a base class. See the following section of this chapter as well as Chapter 4, Defining functions for more information.
Here are some sample situations where you may prefer functional programming constructs instead of procedural ones.
Instead of:
boolean result = false; for (Iterator iter = list.iterator(); iter.hasNext();) { SomeClass next = (SomeClass) iter.next(); if (next.isValid()) { result = true; break; } }You can use:
DynReflect reflect = new JdkDynReflect(); Function1 f = reflect.instanceFunction(SomeClass.class, "valid").f1(); return Functions.any(f, list);
Instead of:
boolean result = true; for (Iterator iter = list.iterator(); iter.hasNext();) { SomeClass next = (SomeClass) iter.next(); if (!next.isValid()) { result = false; break; } }You can use:
Function1 f = reflect.instanceFunction(SomeClass.class, "valid").f1(); boolean result = Functions.all(f, list);
Instead of:
List keep = new ArrayList(); for (Iterator iter = list.iterator(); iter.hasNext();) { SomeClass next = (SomeClass) iter.next(); if (next.isValid()) { keep.add(next); } }You can use:
Function1 f = reflect.instanceFunction(SomeClass.class, "valid").f1(); List keep = Functions.filter(f, list);
Instead of:
List original = ...; // list of positive and negative Integers List positive = new ArrayList(); for (Iterator iter = original.iterator(); iter.hasNext();) { Integer next = (Integer) iter.next(); Integer pos = new Integer(Math.min(0, next.intValue())); positive.add(pos); }You can use:
List original = ...; // list of positive and negative Integers Function1 f = reflect.staticFunction(Math.class, "min").f2().bind(new Integer(0)); List positive = Functions.map(f, original);
Instead of:
List results = new ArrayList(); int size1 = list1 == null ? 0 : list1.size(); int size2 = list2 == null ? 0 : list2.size(); for (int i = 0, t = Math.min(size1, size2); i < t; i++) { results.add(SomeClass.someMethod(list1.get(i), list2.get(i)); }You can use:
Function2 f = reflect.staticFunction(SomeClass.class, "someMethod").f2(); List results = Tuples.zipWith(f, list1, list2);
Functions are defined using interfaces, according to the number of parameters accepted by the function. Interfaces are defined for functions that accept 0 to 4 parameters, as well as an arbitrary number of parameters. For the JDK 1.5 version, you can also use generic types for the function's result and parameters:
Function0<R>Function1<R,P1>Function2<R,P1,P2>Function3<R,P1,P2,P3>Function4<R,P1,P2,P3,P4>FunctionN<R>
public ReturnType method(ParameterType parameter, ...)
All of the FunctionX interfaces contain a
call() method, with the appropriate parameters,
which calls the function and returns the result. All of the interfaces except
Function0 also contain other methods; see the
Javadocs for more
details.
To make it easy to define a function, there are abstract base classes that implement
all methods of the function interfaces except for the
call() method. These classes have the
Impl suffix. For example:
// function that returns a Boolean, expects 2 parameters, of type Integer // and String Function2<Boolean,Integer,String> isLongerThan = new Function2Impl<Boolean,Integer,String>() { // The types below are in the same order as in the above declaration public Boolean call(Integer p_length, String p_string) { return p_string.length() > p_length; } }; assertTrue(isLongerThan.call(2, "ABCDE"));
You can bind parameters to a function without calling it, which will return a new function with those parameters being bound. Thus the new function will be a function of less parameters than the original function. When you bind a number of parameters that is less than the number of parameters expected by the function, this is also known as partial application.
Each function interface has a bind method to bind a
parameter and obtain a function of one less parameter than the original function. For
functions of more than one parameter, you can also bind the parameter at any
position. For example:
Function2<Integer,Integer,Integer> multiply = Operators.multiply; Function1<Integer,Integer> triple = multiply.bind(3); assertEquals(triple.call(9), new Integer(27)); Function2<Integer,Integer,Integer> subtract = Operators.subtract; Function1<Integer,Integer> minus4 = subtract.bind2(4); assertEquals(minus4.call(5), new Integer(1));
A function of 1 parameter f can be
composed with another function
g to obtain a new function
h, where h(x) =
f(g(x)). There are compose
methods in the Function1 interface to support this.
For example:
List<String> strings = Arrays.asList(" AbCd ", "a", " EF ", " 5"); DynReflect reflect = new JdkDynReflect(); Function1<String,String> lowerTrim = reflect.instanceFunction(String.class, "trim").f1().compose( reflect.instanceFunction(String.class, "toLowerCase") ).f1(); List<String> result = Functions.map(lowerTrim, strings); assertEquals(result, Arrays.asList("abcd", "a", "ef", "5"));See Section 4.3, “Function composition” for more information.
Besides defining functions by subclassing a base class or implementing an interface, FunctionalJ also provides mechanisms that use reflection to define a function that refers to an existing constructor or a method.
There are two interfaces that define obtaining functions using reflection: the standard reflection interface and the dynamic reflection interface:
StdReflectDynReflect
Here is an example of obtaining a function that corresponds to the static method
String.valueOf(Object):
DynReflect reflect = new JdkDynReflect(); FunctionN<String> valueOf = reflect.staticFunction(String.class, "valueOf"); assertEquals(valueOf.call(Arrays.asList(1, 2)), "[1, 2]");
Higher-order functions are functions that accept other functions
as parameters, or return functions as a result. In FunctionalJ, higher-order
functions are defined as static methods in the
Functions class.
The Functions class contains methods for mapping,
filtering, scanning and folding. Mapping consists of calling a
1-parameter function on a list of parameters to obtain a list of results.
Filtering uses a 1-parameter function that returns a boolean
result to obtain, from a list of parameters, those for which the function returns
true. Scanning uses a
2-parameter function, a starting parameter, and a list of parameters to return
successive results of calling the function with the previous result and the next
parameter. Folding is similar to scanning, but only returns the
last result.
Here is an example of mapping:
Function1<Integer,String> length = new Function1Impl<Integer,String>() { public Integer call(String p_string) { return Strings.length(p_string); } }; List<String> strings = Arrays.asList("A", "bb", null, "a b c d e"); List<Integer> lengths = Functions.map(length, strings); assertEquals(lengths, Arrays.asList(1, 2, 0, 9));Chapter 6, Using higher-order functions contains more information.
Tuples are groups of data. FunctionalJ provides classes to form
groups of two, three or four, named Pair,
Triple and
Quadruple respectively.
The Tuples class contains methods to work with
tuples. For example, if you have two lists of objects and want to work with the
corresponding pairs of objects from the two lists, you can use
zip:
List<String> list1 = Arrays.asList("A", "b", "C", "d"); List<Integer> list2 = Arrays.asList(1, 2, 3, 4); List<Pair<String,Integer>> pairs = Tuples.zip(list1, list2); assertEquals(pairs.toString(), "[(A, 1), (b, 2), (C, 3), (d, 4)]");The
zipWith method is a generalization of
zip. It successively calls a function with
corresponding parameters from lists, and returns a list of the results. For example:
List<Integer> list1 = Arrays.asList(1, 2, 3, 4); List<Integer> list2 = Arrays.asList(5, 6, 7, 8, 9); Function2<Integer,Integer,Integer> multiply = Operators.multiply; List<Integer> products = Tuples.zipWith(multiply, list1, list2); assertEquals(products.toString(), "[5, 12, 21, 32]");Note that in the above example, the lists are of unequal length. When this is the case, the zipping methods automatically ignore trailing elements.
Refer to Chapter 7, Using tuples for more details.
While FunctionalJ is primarily about using functional programming patterns, it also
provides some practical methods for common tasks. These methods are used by the
library itself; but since they are generally useful, they are available for reuse in
the classes of the util package.
Many of these methods deal with null for you to
avoid getting a NullPointerException and clearing
your code of checks for a null value. For example,
to obtain the size of a list which may be null,
considering a null list to have a size of 0, you can
use Lists.sizeOf(Collection):
List list = ...; // might be null for (int i = 0, t = Lists.sizeOf(list); i < t; i++) { // ... }Similarily, to iterate over a collection or an array, using the
: notation available in JDK 1.5, you can avoid a
NullPointerException by considering a
null collection or array as being empty:
Collection<String> strings = ...; // might be null for (String string : Lists.iterable(strings)) { // ... }For more information, see Chapter 8, Utilities.