package ar.com.javacuriosities.lambdas; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BiPredicate; import java.util.function.BinaryOperator; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.function.UnaryOperator; /* * Se agrego el paquete java.util.function el cual contiene un conjunto * bien definido de Functional Interfaces. * Muchas de estas nuevas interfaces son usadas por el nuevo API de Streams */ public class Lesson03FunctionalInterfaces { public static void main(String[] args) { // Consumer<T>: Esta interfaz solo toma un valor y no retorna valor Consumer<String> consumer = (String message) -> System.out.println(message); // BiConsumer<T, U>: Esta interfaz toma dos valores y no tiene resultado BiConsumer<String, String> biconsumer = (String key, String value) -> System.out.println("Key: " + key + ", Value: " + value); // Supplier<T>: Esta interfaz es lo contrario de un consumer, esta no recibe parámetros y retorna un tipo genérico Supplier<String> supplier = () -> "Logging Message"; // Function<T, R>: Esta interfaz puede ser asociada como una función matemática que toma un valor y devuelve otro (Este puede ser del mismo tipo o no) Function<String, Integer> functionLength = (String message) -> message.length(); Function<String, String> functionToUpperCase = (String message) -> message.toUpperCase(); // BiFunction<T, U, R>: Esta interfaz recibe dos parametros y retorna un valor BiFunction<String, String, String> functionConcatenate = (String left, String right) -> left + " " + right; // UnaryOperator<T>: Es una especialización de Function pero es un tipo especifico donde el argumento y el tipo de resultado son el mismo UnaryOperator<String> functionToLowerCase = (String message) -> message.toLowerCase(); // BinaryOperator<T>: Es una especialización de BiFunction pero los dos argumentos y el tipo de resultado son el mismo BinaryOperator<String> functionLongestString = (String text1, String text2) -> { if (text1.length() > text2.length()) return text1; return text2; }; // Predicate: Es una especialización de Function que siempre retorna Boolean Predicate<Integer> isEven = (Integer number) -> number % 2 == 0; // BiPredicate: ES una especialización de BiFunction que toma dos parámetros y retorna Boolean BiPredicate<Integer, Integer> isGreaterThan = (Integer number, Integer lowerBound) -> number > lowerBound; BiPredicate<Integer, Integer> isLowerThan = (Integer number, Integer upperBound) -> number < upperBound; System.out.println("******************************"); consumer.accept("Hello World"); biconsumer.accept("Cosme", "Fulanito"); System.out.println(supplier.get()); System.out.println("Length: " + functionLength.apply("Hello World")); System.out.println("Upper Case: " + functionToUpperCase.apply("Hello World")); System.out.println("Concatenate: " + functionConcatenate.apply("Cosme", "Fulanito")); System.out.println("Lower Case: " + functionToLowerCase.apply("Hello World")); System.out.println("Longest String: " + functionLongestString.apply("Java", "Rocks")); System.out.println("Is Even: " + isEven.test(2)); System.out.println("Is Greater Than: " + isGreaterThan.test(10, 100)); System.out.println("Is Lower Than: " + isLowerThan.test(10, 100)); /* * Además podemos usar distintos métodos como * - andThen * - compose * - or * - and * - negate */ System.out.println("******************************"); System.out.println(functionToLowerCase.andThen(functionToUpperCase).apply("Java Rocks")); System.out.println(functionToLowerCase.compose(functionToUpperCase).apply("Java Rocks")); System.out.println(isGreaterThan.or(isLowerThan).test(100, 10)); System.out.println(isGreaterThan.and(isLowerThan).test(100, 10)); System.out.println(isEven.negate().test(11)); } }