java functional programming Lambda Expression Functional Interface Method Reference Constructor Reference Interface Streams The java.time Package


Working with streams, lambda expressions, and method references in Java SE8 and beyond

Lambda Expression

  • Assigned to Single Abstract Method (SAM) interface (functional interface) (ex: Runnable, file)
  • Parameter types inferred from context
  • Method Reference

Functional Interface

JavaDoc

  • see java.util.function package
  • Functional Interfaces (Not Required but useful)
  • Use Pure Function
  • Consumer -> single arg, no result (not a Pure function)
    void accept(T t)
    Ex : print or log
    Also IntConsumer, LongConsumer, BiConsumer<T, U>

Ex :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.function.Consumer;
import java.util.logging.Logger;
import java.util.stream.Stream;

public class {
public static void main(String[] args) {
Consumer<String> cPrinter = System.out::println;
Logger logger = Logger.getLogger(ConsumerCompositionDemo.class.getName());

Consumer<String> cLogger = logger::info;

Consumer<String> composed = cPrinter.andThen(cLogger);

Stream.of("This", "is", "a", "string").forEach(composed);

}
}

  • Predicate -> returns boolean
    boolean test(T t)

  • Supplier -> no arg, returns single result
    T get()

    Also BooleanSupplier…

  • Function -> single arg, returns result
    R apply(T t)

Also IntFunction, LongFunction, ToDoubleFunction, ToDoubleBiFunction<T,​U>, ToDoubleFunction, ToIntBiFunction<T,​U>, ToIntFunction, ToLongBiFunction<T,​U> Represents a function that accepts two arguments and produces a long-valued result.
ToLongFunction

Method Reference

Method references uses :: notation

System.out::println equivalent to x -> System.out.println(x)
Math::max equivalent to (x, y) -> Math.max(x, y)
String::compareToIgnoreCase equivalent to (x, y) -> x.compareToIgnoreCase(y)

Constructor Reference

Constructor references uses :: notation

Ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class UsePerson {
({"UnusedAssignment", "Convert2MethodRef"})
public static void main(String[] args) {
List<String> names = Arrays.asList("John", "Paul", "George", "Ringo");

List<Person> people = names.stream()
.map(name -> new Person(name)) // Stream<Person>
.collect(Collectors.toList()); // Converts Stream<Person> to List<Person>


people = names.stream()
.map(Person::new)
.collect(Collectors.toList());

System.out.println(people);

Person[] peopleArray = names.stream()
.map(Person::new)
.toArray(Person[]::new);

System.out.println(Arrays.toString(peopleArray));
}
}

Interface

Default methods

Use keyword default

If conflict :

  • Class vs Interface => Class always wins
  • Interface vs Interface => Child overrides parent, otherwise compilation error

If class implements multiple Interface with same method

  • Must call InterfaceName.super.method
1
2
3
4
5
6
public class Pegasus implements Horse, Bird {
@Override
public String speak() {
return Horse.super.speak() + " " + Bird.super.speak();
}
}

Streams

Definition

A sequence of elements

  • Does not store the elements
  • Does not change the source
  • Operations are lazy when possible
  • Closed when terminal expression reached

A stream carries values

  • from a source
  • through a pipeline

Java Doc

Pipeline

A pipeline is

  • a source
  • zero or more intermediate operations
  • a terminal operation

Reduction Operations

Terminal operation that produce one value for a stream
Ex: average, sum, max, min, count, ....

The java.time Package