such an interface is also called Single Abstract Method (SAM)
@FunctionalInterface is optional but recommended and used to mark functional interfaces and to raise a compile-time error if an interface doesn’t satisfy the requirements of a functional interface.
static and default methods are allowed in functional interfaces because these methods are not abstract
The name of the method is arbitrary and can be anything, and you need to invoke the function using the name defined in the functional interface
@FunctionalInterfacepublic interface GreetingMessage { public abstract void greet(String name)}
Functional Interfaces can inherit another interface if it contains only static or default methods in it. how about private???
instance method of a ObjectType - ObjectType::instanceMethod
constructor reference - ClassName::new
// Both below are same(Square square) -> { return square.calculateArea() }Square::calculateArea// static method(args) -> Class.staticMethod(args)Class::staticMethod// instance method(args) -> obj.instanceMethod(args)obj::instanceMethod// instance method of a ObjectType(obj, args) -> obj.instanceMethod(args)ObjectType::instanceMethod// constructor references(args) -> new ClassName(args)ClassName::new
Using Anonymous class
Func<Long, Long> square = new Func<Long, Long>() { @Override public Long apply(Long val) { return val * val; }};
Built in Functional Interfaces
package: java.util.function
They can be classified as follows:
functions: accept argument produce result
example: Function<T, R>
apply()
operators: produce result of the same type as argument
example: UnaryOperator<T>
apply()
predicates: accept argument and return boolean
example: Predicate<T>
test()
more methods: and(), negate(), or(), not()
suppliers: accept nothing and return values
example: Supplier<T>
get()
consumers: accept argument and return no result
example: Consumer<T>
accept()
more methods: andThen()
Functions
// String to Integer functionFunction<String, Integer> converter = Integer::parseInt;converter.apply("1000"); // the result is 1000 (Integer)// String to int functionToIntFunction<String> anotherConverter = Integer::parseInt;anotherConverter.applyAsInt("2000"); // the result is 2000 (int)// (Integer, Integer) to Integer functionBiFunction<Integer, Integer, Integer> sumFunction = (a, b) -> a + b;sumFunction.apply(2, 3); // it returns 5 (Integer)
Operators
// Long to Long multiplierUnaryOperator<Long> longMultiplier = val -> 100_000 * val;longMultiplier.apply(2L); // the result is 200_000L (Long)// int to int operatorIntUnaryOperator intMultiplier = val -> 100 * val;intMultiplier.applyAsInt(10); // the result is 1000 (int)// (String, String) to String operatorBinaryOperator<String> appender = (str1, str2) -> str1 + str2;appender.apply("str1", "str2"); // the result is "str1str2"
Predicates
// Character to boolean predicatePredicate<Character> isDigit = Character::isDigit;isDigit.test('h'); // the result is false (boolean)// int to boolean predicateIntPredicate isEven = val -> val % 2 == 0;isEven.test(10); // the result is true (boolean)
Suppliers
Supplier<String> stringSupplier = () -> "Hello";stringSupplier.get(); // the result is "Hello" (String)BooleanSupplier booleanSupplier = () -> true;booleanSupplier.getAsBoolean(); // the result is true (boolean)IntSupplier intSupplier = () -> 33;intSupplier.getAsInt(); // the result is 33 (int)
Consumers
// it prints a given stringConsumer<String> printer = System.out::println;printer.accept("!!!"); // It prints "!!!"
Misc functions
Runnable
Does not return or throw anything
package: java.lang
Runnable
void run()
Callable
Can return value or throw exception
package: java.util.concurrent
Callable<V>
V call() throws Exception
Comparator
Return: negative (o1<o2), zero (o1==o2), positive (o1>o2)
package: java.util
Comparator<T>
int compare(T o1, T o2)
Have you ever implemented a functional interface
Yes, defined a method which takes a mapper, which we can use and apply internally