Key notes from Java 8-17 coding exercises
Major Functional Interfaces used in Stream API
| Functional Interface | Input | Output | Used in Intermediate Operations? | Used in Terminal Operations? | Purpose | Example (your preferred style) |
|---|---|---|---|---|---|---|
| Predicate<T> | 1 | boolean | Yes | Yes (some) | Test / filter condition | filter(n -> n % 2 == 0) |
| Function<T, R> | 1 | any type R | Yes | No | Transform / map one value to another | map(s -> s.toUpperCase()) |
| Consumer<T> | 1 | void | No | Yes | Perform side-effect (print, log, etc.) | forEach(System.out::println) |
| Supplier<T> | 0 | any type T | No | No | Generate / supply a value (no input) | Stream.generate(() -> new Random().nextInt(1, 51)) |
| Interface | Stream Operation Type | Classic Example in Stream | Terminal or Intermediate? |
|---|---|---|---|
| Predicate | filter, anyMatch, allMatch, noneMatch | .filter(...), .anyMatch(...) | Intermediate + some Terminal |
| Function | map, flatMap | .map(...), .flatMap(...) | Intermediate |
| Consumer | forEach | .forEach(...) | Terminal |
| Supplier | generate (only) | Stream.generate(Supplier) | Intermediate (creates stream) |
Class Random
=> Random is a class used to provide random behavior
=> We can use Random with Supplier functional interface to generate random number
Example : Generate random numbers between 2 to 100
Random random = new Random();
Supplier<Integer> supplier = () -> random .nextInt(2, 101)) ; //2 to 100 inclusive (bound is exclusive)
//If Interviewer wants modern way random.ints
Supplier<Integer> supplier1 = () -> random.ints(2, 101).findFirst().orElse(2);
//Thread-safe version (if interviewer asks about concurrency)
Supplier<Integer> supplier2 = () -> ThreadLocalRandom.current().nextInt(2, 101);
Comparator
Summary – Which to Prefer?
| Style | Recommendation | When to Use |
|---|---|---|
Comparator.comparing(Employee::getSalary) | Best (cleanest) | Default choice – readable & type-safe |
Comparator.comparing(emp -> emp.getSalary()) | Good | When you need logic inside the lambda |
Comparator.comparingInt(Employee::getSalary) | Good | When salary is primitive int and you want explicit unboxing |
Comparator.comparingInt(emp -> emp.getSalary()) | Your current | Fine, but m.sorted(Comparator.comparing(Employee::getSalary).reversed())ethod reference is slightly better |
.sorted((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary()))
For descending order (if needed later)
.sorted(Comparator.comparing(Employee::getSalary).reversed())