STUDYECRAT Java : Functional Interface
60s
Java Functional Interface
Prove your skills in this interactive quiz
Live Code
Run snippets directly
Timed
60s per question
Scored
Earn 3D badges
★ Java 8 Functional Interfaces: Key Interview Points
1. The Big Four Functional Interfaces
Function<String, Integer> strToInt = Integer::parseInt;
Predicate<String> isLong = s -> s.length() > 10;
Consumer<String> printer = System.out::println;
Supplier<Double> random = Math::random;
// Each serves distinct purpose: transform, test, consume, supply
Predicate<String> isLong = s -> s.length() > 10;
Consumer<String> printer = System.out::println;
Supplier<Double> random = Math::random;
// Each serves distinct purpose: transform, test, consume, supply
- Tip: Prefer primitive variants (IntPredicate) when working with primitives for better performance
- Real Use: Stream.filter() uses Predicate, Stream.map() uses Function
2. Method Reference Nuances
List<String> names = Arrays.asList("A", "B", "C");
names.forEach(System.out::println); // Instance method
Function<String, String> upper = String::toUpperCase; // Bound instance
BiFunction<String, String, String> concat = String::concat; // Unbound instance
// :: syntax adapts to functional interface context
names.forEach(System.out::println); // Instance method
Function<String, String> upper = String::toUpperCase; // Bound instance
BiFunction<String, String, String> concat = String::concat; // Unbound instance
// :: syntax adapts to functional interface context
- Tip: Class::method can mean either static method or instance method depending on context
- Real Use: Optional.ifPresent() often uses System.out::println
3. Function Composition
Function<Integer, Integer> square = x -> x * x;
Function<Integer, String> toString = Object::toString;
// Execution order differences:
Function<Integer, String> a = square.andThen(toString); // square → toString
Function<Integer, String> b = toString.compose(square); // square → toString
// andThen vs compose direction matters!
Function<Integer, String> toString = Object::toString;
// Execution order differences:
Function<Integer, String> a = square.andThen(toString); // square → toString
Function<Integer, String> b = toString.compose(square); // square → toString
// andThen vs compose direction matters!
- Tip: Debug composition chains with peek(): x -> { System.out.println(x); return x; }
- Real Use: Spring's functional WebFlux uses composition heavily
4. Avoiding Auto-boxing
// Standard vs primitive versions:
Function<Integer, Integer> f1 = x -> x * 2; // Boxed
IntUnaryOperator f2 = x -> x * 2; // Primitive
LongPredicate isEven = l -> l % 2 == 0; // Better than Predicate<Long>
// Primitive variants prevent costly boxing
Function<Integer, Integer> f1 = x -> x * 2; // Boxed
IntUnaryOperator f2 = x -> x * 2; // Primitive
LongPredicate isEven = l -> l % 2 == 0; // Better than Predicate<Long>
// Primitive variants prevent costly boxing
- Tip: Look for ToIntFunction, DoubleConsumer, etc. in performance-critical code
- Real Use: Stream.sum() uses primitive streams (IntStream) internally
5. Creating Your Own
@FunctionalInterface
interface TriFunction<A,B,C,R> {
R apply(A a, B b, C c);
}
TriFunction<String, Integer, Boolean, String> tri =
(s,i,b) -> s + i + b;
// @FunctionalInterface enforces single abstract method
interface TriFunction<A,B,C,R> {
R apply(A a, B b, C c);
}
TriFunction<String, Integer, Boolean, String> tri =
(s,i,b) -> s + i + b;
// @FunctionalInterface enforces single abstract method
- Tip: Always annotate with @FunctionalInterface to prevent accidental method additions
- Real Use: Java's BiFunction is insufficient for 3+ parameters
💡 Pro Interview Tip
When asked about functional interfaces, always mention the four key variants (Function, Predicate, Consumer, Supplier) and demonstrate composition. Interviewers love seeing candidates who can chain operations like filter.map.reduce
fluently.