Chapter 15 Functional Programming Notes Flashcards

1
Q

Common functional interfaces

A
  1. Supplier<T>, T get()
  2. Consumer<T>, void accept(T)
  3. BiConsumer<T, U>, void accept(T,U)
  4. Predicate<T>, boolean test(T)
  5. BiPredicate<T, U>, boolean test(T,U)
  6. Function<T, R>, R apply(T)
  7. BiFunction<T, U, R>, R apply(T,U)
  8. UnaryOperator<T>, T apply(T)
  9. BinaryOperator<T>, T apply(T,T)

All of the functional interfaces in the list are provided in the java.util.function package.
The convention here is to use the generic type T for the type parameter. If a second type parameter is needed, the next letter, U, is used. If a distinct return type is needed, R for return is used for the generic type.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

> [!NOTE]
As you’ll learn in Chapter 18, “Concurrency,” there are two more functional interfaces called Runnable and Callable, which you need to know for the exam. They are used for concurrency the majority of the time. However, they may show up on the exam when you are asked to recognize which functional interface to use. All you need to know is that Runnable and Callable don’t take any parameters, with Runnable returning void and Callable returning a generic type.

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

IMPLEMENTING SUPPLIER

The Supplier interface is defined as follows:

@FunctionalInterface
public interface Supplier<T> {
    T get();
}
A

This example shows how to use a Supplier to call this factory:

Supplier<LocalDate> s1 = LocalDate::now;
Supplier<LocalDate> s2 = () -> LocalDate.now();
LocalDate d1 = s1.get();
LocalDate d2 = s2.get();
System.out.println(d1);
System.out.println(d2);

A Supplier is often used when constructing new objects. For example, we can print two empty StringBuilder objects.

Supplier<StringBuilder> s1 = StringBuilder::new;
Supplier<StringBuilder> s2 = () -> new StringBuilder();
System.out.println(s1.get());
System.out.println(s2.get());
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Can you figure out what the following does? Just take it one step at a time.

Supplier<ArrayList<String>> s3 = ArrayList<String>::new;
ArrayList<String> a1 = s3.get();
System.out.println(a1);
A
  • We have a Supplier of a certain type. That type happens to be ArrayList<String>.</String>
  • Then calling get() creates a new instance of ArrayList<String>, which is the generic type of the Supplier—in other words, a generic that contains another generic. It's not hard to understand, so just look at the code carefully when this type of thing comes up.</String>

if we tried to print out s3 itself?

System.out.println(s3);

The code prints something like this:

functionalinterface.BuiltIns\$\$Lambda$1/0x0000000800066840@4909b
8da

Our test class is named BuiltIns, and it is in a package that we created named functionalinterface. Then comes $$, which means that the class doesn’t exist in a class file on the file system. It exists only in memory. You don’t need to worry about the rest.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

IMPLEMENTING CONSUMER AND BICONSUMER

The interfaces are defined as follows:

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
// omitted default method
}

@FunctionalInterface
public interface BiConsumer<T, U> {
    void accept(T t, U u); 
// omitted default method
}
A

Here’s that example actually being assigned to the Consumer interface:

Consumer<String> c1 = System.out::println;
Consumer<String> c2 = x -> System.out.println(x);
c1.accept("Annie");
c2.accept("Annie");

For example, we can put a key and a value in a map using this interface:

var map = new HashMap<String, Integer>();
BiConsumer<String, Integer> b1 = map::put;
BiConsumer<String, Integer> b2 = (k, v) -> map.put(k, v);
b1.accept("chicken", 7);
b2.accept("chick", 1);
System.out.println(map);

The output is {chicken=7, chick=1}

As another example, we use the same type for both generic parameters.

var map = new HashMap<String, String>();
BiConsumer<String, String> b1 = map::put;
BiConsumer<String, String> b2 = (k, v) -> map.put(k, v);
b1.accept("chicken", "Cluck");
b2.accept("chick", "Tweep");
System.out.println(map);

The output is {chicken=Cluck, chick=Tweep}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

> [!NOTE]
You’ll notice this pattern. Bi means two. It comes from Latin, but you can remember it from English words like binary (0 or 1) or bicycle (two wheels). Always add another parameter when you see Bi show up.

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly