Key notes from Java 8-17 coding exercises

Major Functional Interfaces used in Stream API

Functional InterfaceInputOutputUsed in Intermediate Operations?Used in Terminal Operations?PurposeExample (your preferred style)
Predicate<T>1booleanYesYes (some)Test / filter conditionfilter(n -> n % 2 == 0)
Function<T, R>1any type RYesNoTransform / map one value to anothermap(s -> s.toUpperCase())
Consumer<T>1voidNoYesPerform side-effect (print, log, etc.)forEach(System.out::println)
Supplier<T>0any type TNoNoGenerate / supply a value (no input)Stream.generate(() -> new Random().nextInt(1, 51))

InterfaceStream Operation TypeClassic Example in StreamTerminal or Intermediate?
Predicatefilter, anyMatch, allMatch, noneMatch.filter(...), .anyMatch(...)Intermediate + some Terminal
Functionmap, flatMap.map(...), .flatMap(...)Intermediate
ConsumerforEach.forEach(...)Terminal
Suppliergenerate (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?

StyleRecommendationWhen to Use
Comparator.comparing(Employee::getSalary)Best (cleanest)Default choice – readable & type-safe
Comparator.comparing(emp -> emp.getSalary())GoodWhen you need logic inside the lambda
Comparator.comparingInt(Employee::getSalary)GoodWhen salary is primitive int and you want explicit unboxing
Comparator.comparingInt(emp -> emp.getSalary())Your currentFine, but m.sorted(Comparator.comparing(Employee::getSalary).reversed())ethod reference is slightly better
Old-school (pre-Java 8 style — avoid in modern code)

.sorted((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary()))

For descending order (if needed later)

 .sorted(Comparator.comparing(Employee::getSalary).reversed())