Chapter 6 Lambdas and Functional Interfaces Notes Flashcards
Lambdas and Functional Interfaces
Java 8
introduce Functional programming- Functional programming is a way of writing code more declaratively.
- Functional programming uses lambda expressions to write code.
- A lambda expression is a block of code that gets passed around.
- You can think of a lambda expression as an unnamed method.
- In other words, a lambda expression is like a method that you can pass as if it were a variable.
Lambda syntax
// omitting optional parts a -> a.canHop() // including optional parts (Animal a) -> {return a.canHop();}
- A single parameter specified with the name a and stating the type is Animal
- The arrow operator to separate the parameter and body
- A body that has one or more lines of code, including a semicolon and a return statement
The parentheses can be omitted only if there is a single parameter and its type is not explicitly stated.
can omit braces when we have only a single statement.
Java doesn’t require you to type return or use a semicolon when no braces are used.
> [!NOTE:] s -> {}
is a valid lambda. If there is no code on the right side of the expression, you don’t need the semicolon or return statement.
s -> {}
Valid?
() -> true a -> a.startsWith("test") (String a) -> a.startsWith("test") (a, b) -> a.startsWith("test") (String a, String b) -> a.startsWith("test")
Valid lambdas
() -> true // 0 parameter a -> a.startsWith("test") // 1 parameter (String a) -> a.startsWith("test") // 1 parameter (a, b) -> a.startsWith("test") // 2 parameter (String a, String b) -> a.startsWith("test") // 2 parameter
The final two rows take two parameters and ignore one of them—there isn’t a rule that says you must use all defined parameters.
Valid?
a, b -> a.startsWith("test") a -> { a.startsWith("test"); } a -> { return a.startsWith("test") }
Invalid
a, b -> a.startsWith("test") // Missing parenthese a -> { a.startsWith("test"); } // Missing return a -> { return a.startsWith("test") } // Missing semicolon
Functional Interfaces
Lambdas work with interfaces that have only one abstract method. These are called functional interfaces.
Single Abstract Method (SAM).
> [!NOTE]
Java provides an annotation @FunctionalInterface on some, but not all, functional interfaces. This annotation means the authors of the interface promise it will be safe to use in a lambda in the future. However, just because you don’t see the annotation doesn’t mean it’s not a functional interface. Remember that having exactly one abstract method is what makes it a functional interface, not the annotation.
@FunctionalInterface
There are four functional interfaces you are likely to see on the exam.
It’s in the package java.util.function
1. Predicate
public interface Predicate<T> { boolean test(T t); }
2. Consumer
void accept(T t)
3. Supplier
T get()
4. Comparator (in java.util package)
int compare(T o1, T o2)
Predicate example:
1: import java.util.*; 2: import java.util.function.*; 3: public class PredicateSearch { 4: public static void main(String[] args) { 5: List<Animal> animals = new ArrayList<Animal>(); 6: animals.add(new Animal("fish", false, true)); 7: 8: print(animals, a -> a.canHop()); 9: } 10: private static void print(List<Animal> animals, 11: Predicate<Animal> checker) { 12: for (Animal animal : animals) { 13: if (checker.test(animal)) 14: System.out.print(animal + " "); 15: } 16: System.out.println(); 17: } 18: }
Let’s take a look at code that uses a Consumer:
public static void main(String[] args) { Consumer<String> consumer = x -> System.out.println(x); print(consumer, "Hello World"); } private static void print(Consumer<String> consumer, String value) { consumer.accept(value); }
Let’s take a look at code that uses a Supplier:
public static void main(String[] args) { Supplier<Integer> number = () -> 42; System.out.println(returnNumber(number)); } private static int returnNumber(Supplier<Integer> supplier) { return supplier.get(); }
> [!NOTE]
The Comparator interface existed prior to lambdas being added to Java. As a result, it is in a different package.
You can find Comparator in java.util.
Comparator interface is in java.util.
Sort in ascending or descending order?
Comparator<Integer> ints = (i1, i2) -> i1 - i2; Comparator<String> strings = (s1, s2) -> s2.compareTo(s1); Comparator<String> moreStrings = (s1, s2) -> - s1.compareTo(s2);
Comparator<Integer> ints = (i1, i2) -> i1 - i2; // ascending Comparator<String> strings = (s1, s2) -> s2.compareTo(s1); // descending. Comparator<String> moreStrings = (s1, s2) -> - s1.compareTo(s2); // ascending
Working with Variables in Lambdas
Variables can appear in three places with respect to lambdas: the parameter list, local variables declared inside the lambda body, and variables referenced from the lambda body. All three of these are opportunities for the exam to trick you. We will explore each one so you’ll be alert when tricks show up!
var can be used in place of the specific type.
identify the type of the lambda parameter.
all three of these statements are interchangeable:
~~~
Predicate<String> p = x -> true;
Predicate<String> p = (var x) -> true;
Predicate<String> p = (String x) -> true;
~~~</String></String></String>
String
Can you figure out the type of x?
public void whatAmI() { consume((var x) -> System.out.print(x), 123); } public void consume(Consumer<Integer> c, int num) { c.accept(num); }
Integer
What do you think the type of x is here?
public void counts(List<Integer> list) { list.sort((var x, var y) -> x.compareTo(y)); }
Integer