People have been complaining about the naming of Java 8's functional interfaces in the java.util.function package. Depending on the types of arguments and return values a function may instead be called a consumer, supplier, predicate or operator, which is further complicated by two-argument functions. The number of interfaces explodes because of specialized interfaces for some primitive types. In total there are 43 interfaces in that package. Compare this to Scala where just three interfaces (with compiler optimizations) cover all the same use cases: Function0, Function1 and Function2.

To make some sense out of this all, I wrote a program that generates the interface names based on the function's argument types and return type. The names it generates match those in the Java library. For this article I also made visualization which you can see below.

Visually

Click to make it bigger.

Textually

The interface name is determined by the following algorithm. The names are described as regular expressions; the generic interfaces have the shortest names, but specialized interfaces for functions taking or returning primitives include the primitive types in the interface name.

Does it return void? Arity 0: Runnable

Arity 1: (|Int|Long|Double)Consumer

Arity 2: Both arguments are generic: BiConsumer First argument is generic: Obj(Int|Long|Double)Consumer

Does it take no arguments? Arity 0: (|Int|Long|Double|Boolean)Supplier Does it return boolean? Arity 1: (|Int|Long|Double)Predicate

Arity 2: BiPredicate Do all arguments have the same type as the return value? Arity 1: (|Int|Long|Double)UnaryOperator

Arity 2: (|Int|Long|Double)BinaryOperator Otherwise: Arity 1: (|Int|Long|Double)(|ToInt|ToLong|ToDouble)Function

Arity 2: (|ToInt|ToLong|ToDouble)Function

The method names follow. When the return type is a primitive, the method name is a bit longer (this is apparently because the JVM supports method overloading also based on the method return type, but the Java language does not).

Runnable: run

Consumers: accept

Suppliers: get(|AsInt|AsLong|AsDouble|AsBoolean)

Predicates: test

Functions and operators: apply(|AsInt|AsLong|AsDouble)

I hope that helps some of you in remembering what interface to look for when browsing the API.