Home › Learn › Java › Interfaces, generics, and streams

Lambdas

Lesson 33 of 40. Pass behavior as a value.

A lambda is a small function written in place: x -> x * 2, or (a, b) -> a + b, or with a block x -> { ... return y; }. It can be passed wherever a functional interface (an interface with one abstract method) is expected: Predicate<String> (a test returning boolean), Function<A, B> (a transformation), Comparator<T> (an ordering), Runnable (something to run). Method references are shorthand for a lambda that just calls a method: String::length, System.out::println.

The collections take lambdas everywhere: list.removeIf(w -> w.isEmpty()), list.forEach(System.out::println), list.sort(Comparator.comparing(String::length)). Comparator.comparing(...).reversed() flips the order; thenComparing breaks ties.

List<String> words = new ArrayList<>(List.of("kiwi", "fig", "banana"));
words.sort(Comparator.comparing(String::length));
System.out.println(words);   // [fig, kiwi, banana]
words.removeIf(w -> w.length() < 4);
System.out.println(words);   // [kiwi, banana]

Your task

Write static List<Integer> keep(List<Integer> xs, Predicate<Integer> test) returning a new list of the values that pass the test, static List<String> byLength(List<String> words) returning a new list sorted by length and then alphabetically among equal lengths, and static int applyTwice(Function<Integer, Integer> f, int x) returning f(f(x)).

Hint 1

for (int x : xs) if (test.test(x)) result.add(x);

Hint 2

byLength: copy with new ArrayList<>(words), then copy.sort(Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder())); applyTwice: return f.apply(f.apply(x));

Show the solution
import java.util.*;
import java.util.function.*;

public class Main {
    static List<Integer> keep(List<Integer> xs, Predicate<Integer> test) {
        List<Integer> result = new ArrayList<>();
        for (int x : xs) {
            if (test.test(x)) {
                result.add(x);
            }
        }
        return result;
    }

    static List<String> byLength(List<String> words) {
        List<String> copy = new ArrayList<>(words);
        copy.sort(Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder()));
        return copy;
    }

    static int applyTwice(Function<Integer, Integer> f, int x) {
        return f.apply(f.apply(x));
    }

    public static void main(String[] args) {
        System.out.println(keep(List.of(1, 2, 3, 4), n -> n % 2 == 0) + " " + applyTwice(n -> n * 3, 2));
    }
}

    Compiles with OpenJDK javac and TeaVM, both compiled to WebAssembly (7 MB download the first time, then cached), and runs in this tab; nothing is sent anywhere.