This document discusses lambda functions and new features coming to Java 8, including lambda functions (anonymous functions), method references, default methods in interfaces, and functional interfaces with a single abstract method. It provides examples of lambda functions and explores how they can be used for filtering, mapping, chaining, and iterating over collections.
3. What’s a lambda function?
A.K.A.:
Anonymous function
Anonymous method
Function literal
Function constant
Closure
Wikipedia: “a function (or a subroutine)
defined, and possibly called, without being
bound to an identifier”
Typically can’t be recursive directly
Simple example: (int x, int y) -> x + y
Supported in a bunch of languages…
5. More Examples
x -> x + 1
(x) -> x + 1
(int x) -> x + 1
(int x, int y) -> x + y
(x, y) -> x + y
(x, y) -> { System.out.printf("%d +
%d = %d%n", x, y, x+y); }
() -> { System.out.println("I am a
Runnable"); }
6. Meanwhile, in Java 7…
Functional Interfaces
SAM – “Single Abstract Method”
Interfaces that have just 1 method
java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
7. Meanwhile, in Java 7…
Typically:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.doStuff(e.getModifiers());
}
});
Five lines to do one statement
This would become:
button.addActionListener(e -> { panel.doStuff(e.getModifiers()); });
8. More Anonymous Class Issues(?)
Lexical scoping
What does this mean?
final Runnable r = () -> {
// This reference to 'r' is legal:
if (!allDone) { workQueue.add(r); }
else { displayResults(); }
};
Accessing non-final variables
Lambdas: same variable access as you’d
have just outside the expression
9. java.util.functions
Predicate
List<String> names = Arrays.asList("Alice", "Bob",
"Charlie", "Dave");
List<String> filteredNames = names
.filter(e -> e.length() >= 4)
.into(new ArrayList<String>());
filter: only retain elements where the
predicate holds true
into: fills up an ArrayList with the filtered
elements, then gets set as filteredNames
10. java.util.functions
Block
No more for loops…?
List<String> names = Arrays.asList("Alice", "Bob",
"Charlie", "Dave");
names
.filter(e -> e.length() >= 4)
.forEach(e -> { System.out.println(e); });
forEach: Can only see one element at a
time
Lazy element computation
11. java.util.functions
Method chaining
List<String> names = Arrays.asList("Alice", "Bob",
"Charlie", "Dave");
names
.mapped(e -> { return e.length(); })
.asIterable() // returns an Iterable of BiValue
// elements; an element's key is the
// person's name, its value is the
// string length
.filter(e -> e.getValue() >= 4)
.sorted((a, b) -> a.getValue() - b.getValue())
.forEach(e -> { System.out.println(e.getKey() +
't' + e.getValue()); });
Is method chaining good…?
12. Method References
Can pass around references to methods
like you can with anonymous functions
by using ::
Static and instance methods
Arrays.asList("Alice", "Bob", "Charlie",
"Dave").forEach(System.out::println);
Make factories easily:
Factory<Biscuit> biscuitFactory = Biscuit::new;
Biscuit biscuit = biscuitFactory.make();
13. Default Methods
Currently, interfaces are basically “set in stone”
Altering an interface will break existing implementations
Blurred line between abstract/concrete methods…?
interface Foo {
void bar() default {
System.out.println(“baz”);
}
}
interface AnotherFoo extends Foo {
void bar() default {
System.out.println(“not baz”);
}
}
interface YetAnotherFoo extends Foo {
void bar();
}
-Alonzo Church: formulated lambda calculus as a formal system of expressing computation by way of function composition. Functional programming languages are the most prominent counterpart to lambda calculus, as well as proof theory.-Can’t be recursive because there’s no name associated with the function. Requires an anonymous fixpoint; a higher-order function that creates a fixed point of other functions-If you assign the lambda expression to a variable name, it can then reference itselffinal Runnable r = () -> { // This reference to 'r' is legal: if (!allDone) { workQueue.add(r); } else { displayResults(); } };
Interfaces that have just 1 method: not including stuff inherited from Object, etc.
-Compiler knows that the lambda must conform to the actionPerformed() signature; sees that it returns void, and that e is an ActionEvent
-“this” when unqualified always means the inner class itself-For lambdas, “this” has the same meaning that it does just outside of the lambda-…meaning that the lambda can’t refer to itself directly
-No need to store intermediate results, but you possibly lose the clarity that comes with giving everything a name