Anonymous classes – the old way of functional programming in Java
Collections.sort(words, new Comparator<String> {
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
Functional interface – new way of functional programming in Java
Collections.sort(words, (s1, s2) ->
Integer.compare(s1.length(), s2.length()));
public enum Operation {
PLUS("+") {
public double apply(double x, double y) { return x + y; }
};
MINUS("-") {
public double apply(double x, double y) { return x - y; }
};
MULTIPLY("*") {
public double apply(double x, double y) { return x * y; }
};
DIVIDE("/") {
public double apply(double x, double y) { return x / y; }
};
private final String symbol;
Operation(String symbol) { this.symbol = symbol; }
@Override
public String toString() { return symbol; }
public abstract double apply(double x, double y);
}
public enum Operation {
PLUS("+", (x, y) -> x + y );
MINUS("-", (x, y) -> x - y );
MULTIPLY("*", (x, y) -> x * y );
DIVIDE("/", (x, y) -> x / y );
private final String symbol;
private final DoubleBinaryOperator op;
Operation(String symbol, DoubleBinaryOperator op) {
this.symbol = symbol;
this.op = op;
}
@Override
public String toString() { return symbol; }
public double apply(double x, double y) {
return op.applyAsDouble(x, y);
}
}
// no arguments
() -> System.out.println("Hello")
// one argument
s -> System.out.println(s)
// two arguments
(a, b) -> a + b
// explicit argument types
(Integer a, Integer b) -> a + b
// multiple statements
(a, b) -> {
System.out.println(a);
System.out.println(b);
return a + b;
}
Method references are even shorter way to write some expressions than lambdas
lambda:
map.merge(key, 1, (count, incr) -> count + incr);
method reference:
map.merge(key, 1, Integer::sum);
Reference to a Static Method
method reference:
Integer::parseInt
lambda:
string -> Integer.parseInt(string)
Reference to an Instance Method of a specific object
method reference:
Instant.now()::isAfter
lambda:
Instant then = Instant.now();
t -> then.isAfter(then)
Reference to an Instance Method of an unspecified object
method reference:
String::toLowerCase()
lambda:
string -> string.toLowerCase()
Constructor of an object
method reference:
HashMap<K,V>::new
lambda:
() -> new HashMap<K,V>
Constructor of an array
method reference:
int[]::new
lambda:
length -> new int[length]
java.util.function
UnaryOperator<T>
Signature:
T apply(T t)
Example:
String::toLowerCase
BinaryOperator<T>
Signature:
T apply(T t1, T t2)
Example:
BigInteger:add
Predicate<T>
Signature:
boolean test(T t)
Example:
Collection::isEmpty
Function<T,R>
Signature:
R apply(T t)
Example:
Arrays::asList
Supplier<T>
Signature:
T get()
Example:
Instant::now
Consumer<T>
Signature:
void accept(T t)
Example:
System.out::println
example of use of @FunctionalInterface
Examples of how to use streams
go to code
Optional<T>
examples of how to use optionals and common mistakes
Optional<Movie> movie = Optional.of(library.findMovie(id));
if (movie.isPresent()) {
someLogic;
}
return movie;
Optional<Movie> movie = Optional.of(library.findMovie(id));
movie.ifPresent(() -> someLogic );
return movie;
examples of how to use optionals and common mistakes
public static List<Person> search(List<Person> people, Optional<Integer> age) {
// Null checks for people and name
return people.stream()
.filter(p -> p.getAge().get() >= age.orElse(0))
.collect(Collectors.toList());
}
public static List<Person> search(List<Person> people, Integer age) {
// Null checks for people and name
final Integer ageFilter = age != null ? age : 0;
return people.stream()
.filter(p -> p.getAge().get() >= ageFilter)
.collect(Collectors.toList());
}
examples of how to use optionals and common mistakes
streamOfOptionals
.filter(Optional::isPresent)
.map(Optional::get)
streamOfOptionals
.flatMap(Optional::stream)