Develop code that uses the built-in interfaces included in the java.util.function package, such as Function, Consumer, Supplier, UnaryOperator, Predicate, and Optional APIs, including the primitive and binary variations of the interfaces - Desenvolver código que usa as interfaces embutidas no pacote java.util.function, como Function, Consumer, Supplier, UnaryOperator, Predicate e a API de Optional, incluindo as variações de tipos primitivos e binários das interfaces
O Java 8 possui algumas Interfaces Funcionais já criadas. Elas provavelmente serão suficientes para a maioria dos cenários onde é usual utilizar expressões lambda, de tal forma que não deve ser muito comum você precisar criar uma nova.
É fundamental entender esses exemplos para dominar a utilização de expressões lambda, e para entender a próxima seção sobre referências a métodos.
-
Supplieré uma interface funcional que não recebe nenhum parâmetro de entrada, mas retorna um valor. Sua definição na JDK é a seguinte:java.util.function.Supplier<T>@FunctionalInterface public interface Supplier<T> { T get(); }
-
Uma implementação possível para um
Supplieré um gerador da data atual:src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_SupplierExample.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_SupplierExample.java[role=include]
Saída no console2019-07-08A saída no console irá imprimir a data atual em que este código foi escrito.
Perceba que a expressão lambda está simplificada, sem chaves
{}oureturn. Caso tenha dúvidas com relação a isso, consulte novamente a seção sobre expressões lambda. -
Um
Supplierpode ser utilizado para fornecer uma função custosa em termos de processamento, para que seja chamada apenas se for necessário:src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_SupplierUseCase.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_SupplierUseCase.java[role=include]
Saída no consoleMenor de idade! Maior de idade! Validação realizada às 2019-07-09T00:21:35.488
Perceba que neste caso o supplier só precisou ser chamado na segunda vez, evitando uma execução desnecessária da expressão lambda.
-
Existem interfaces
Supplierpara lidar tipos primitivos:BooleanSupplier,IntSupplier,LongSuppliereDoubleSupplier.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_SupplierPrimitive.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_SupplierPrimitive.java[role=include]
O resultado na console será imprimir o
intprimitivo gerado aleatoriamente.
-
Consumeré uma interface funcional que recebe um parâmetro de entrada, e não retorna nenhum valor. Sua definição na JDK é a seguinte:java.util.function.Supplier<T>@FunctionalInterface public interface Consumer<T> { void accept(T t); }
-
BiConsumeré uma interface funcional que recebe dois parâmetros de entrada, e não retorna nenhum valor. Sua definição na JDK é a seguinte:java.util.function.Consumer<T>@FunctionalInterface public interface BiConsumer<T, U> { void accept(T t, U u); }
-
Implementações possíveis para
ConsumerouBiConsumersão funções que imprimem informações no console:src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_ConsumerExample.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_ConsumerExample.java[role=include]
Saída no console2019-07-08 2019-07-08 22:37:39.229
-
Existem interfaces
Consumerpara lidar tipos primitivos:DoubleConsumer,IntConsumer,LongConsumer,ObjDoubleConsumer,ObjIntConsumereObjLongConsumer.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_ConsumerPrimitive.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_ConsumerPrimitive.java[role=include]
-
Predicateé uma interface funcional que recebe um parâmetro de entrada e retorna um valor booleano. Sua definição na JDK é a seguinte:java.util.function.Predicate<T>@FunctionalInterface public interface Predicate<T> { boolean test(T t); }
-
BiPredicateé uma interface funcional que recebe dois parâmetros de entrada e retorna um valor booleano. Sua definição na JDK é a seguinte:java.util.function.BiPredicate<T>@FunctionalInterface public interface BiPredicate<T, U> { boolean test(T t, U u); }
-
Implementações possíveis para
PredicateouBiPredicatesão funções que verificam se o valor de entrada é igual ao valor sorteado:src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_PredicateExample.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_PredicateExample.java[role=include]
A saída no console é aleatória, pois depende do valor sorteado. Um valor possível seria
falseetrue. -
Existem interfaces
Predicatepara lidar tipos primitivos:DoublePredicate,IntPredicateeLongPredicate.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_PredicatePrimitive.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_PredicatePrimitive.java[role=include]
-
Functioné uma interface funcional que recebe um parâmetro de entrada e retorna um valor. Sua definição na JDK é a seguinte:java.util.function.Function<T, R>@FunctionalInterface public interface Function<T, R> { R apply(T t); }
-
BiFunctioné uma interface funcional que recebe dois parâmetros de entrada e retorna um valor. Sua definição na JDK é a seguinte:java.util.function.BiFunction<T>@FunctionalInterface public interface BiFunction<T, U, R> { R apply(T t, U u); }
-
Implementações possíveis para
FunctionouBiFunctionsão funções que multiplicam os valores fornecidos:src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_FunctionExample.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_FunctionExample.java[role=include]
Saída no console7.5 30.0
-
Existem várias interfaces
Functionpara lidar tipos primitivos:DoubleFunction,DoubleToIntFunction,DoubleToLongFunction,IntFunction,IntToDoubleFunction,IntToLongFunction,LongFunction,LongToDoubleFunction,LongToIntFunction,ToDoubleBiFunction,ToDoubleFunction,ToIntBiFunction,ToIntFunction,ToLongBiFunction,ToLongFunction.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_FunctionPrimitive.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_FunctionPrimitive.java[role=include]
Saída no console7.5 30.0
-
UnaryOperatoré uma interface funcional que recebe um parâmetro de entrada e retorna um valor do mesmo tipo da entrada. Sua definição na JDK é a seguinte:java.util.function.Function<T, R>@FunctionalInterface public interface UnaryOperator<T> extends Function<T, T> { }
Perceba que não existe método abstrato declarado, pois ela apenas estende a interface
Functionjá existente. -
BinaryOperatoré uma interface funcional que recebe dois parâmetros de entrada do mesmo tipo, e retorna um valor do mesmo tipo das entradas. Sua definição na JDK é a seguinte:java.util.function.BiFunction<T>@FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T,T,T> { }
Perceba que não existe método abstrato declarado, pois ela apenas estende a interface
BiFunctionjá existente. -
Implementações possíveis para
UnaryOperatorouBinaryOperatorsão funções que soma um número fixo ou soma um número ao outro:src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OperatorExample.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OperatorExample.java[role=include]
Saída no console9 6
-
Existem interfaces
Operatorpara lidar tipos primitivos:DoubleBinaryOperator,DoubleUnaryOperator,IntBinaryOperator,IntUnaryOperator,LongBinaryOperator,LongUnaryOperator.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OperatorPrimitive.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OperatorPrimitive.java[role=include]
Saída no console9 6
O Java 8 possui um tipo específico para representar valores que podem não ter sido informados, que é a classe Optional. A partir do Java 8, ela geralmente é uma opção melhor do que retornar ou armazenar null, pois seus métodos auxiliam em várias situações.
-
É possível criar uma instância de
Optionalcom valor através do métodoof. -
É possível criar uma instância de
Optionalsem valor através do métodoempty. -
É possível checar se uma instância de
Optionalpossui um valor através do métodoisPresent. -
É possível recuperar o valor de uma instância de
Optionalatravés do métodoget.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalCreation.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalCreation.java[role=include]
-
Não é possível chamar o método
ofpassandonullcomo argumento. Para isso existe o métodoofNullable.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalNullable.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalNullable.java[role=include]
Saída no consolejava.lang.NullPointerException at java.util.Objects.requireNonNull(Objects.java:203) at java.util.Optional.<init>(Optional.java:96) at java.util.Optional.of(Optional.java:108) at org.j6toj8.lambda.builtininterfaces.BuiltInInterfaces_OptionalNullable.main(BuiltInInterfaces_OptionalNullable.java:11) false
-
Com o método
ifPresenté possível executar uma expressão lambda apenas se oOptionaltiver valor.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalIfPresent.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalIfPresent.java[role=include]
Saída no consoleCom Valor: valor -
É possível recuperar um valor padrão caso o
Optionalesteja vazio. O métodoorElseretorna um valor diretamente, e oorElseGetretorna através de uma expressão lambda.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalOrElse.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalOrElse.java[role=include]
Saída no consolevalor padrao valor padrao valor valor
TipObserve que esse é um ótimo caso para lembrar de um benefício das expressões lambda. Na utilização de orElseGeta expressão lambda só é executada caso oOptionalesteja vazio. No caso do exemplo, como é apenas o retorno de umaString, não faz diferença. Porém, se fosse uma operação mais pesada, você só iria de fato executá-la se oOptionalestivesse vazio. Caso houvesse valor, a expressão lambda nem seria executada, evitando o custo de processamento. -
Também é possível lançar uma exceção caso um valor não esteja presente no
Optionalutilizando o métodoorElseThrow.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalOrElseThrow.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalOrElseThrow.java[role=include]
Saída no consolevalor Exception in thread "main" java.lang.RuntimeException at org.j6toj8.lambda.builtininterfaces.BuiltInInterfaces_OptionalOrElseThrow.lambda$1(BuiltInInterfaces_OptionalOrElseThrow.java:17) at java.util.Optional.orElseThrow(Optional.java:290) at org.j6toj8.lambda.builtininterfaces.BuiltInInterfaces_OptionalOrElseThrow.main(BuiltInInterfaces_OptionalOrElseThrow.java:17)
-
Será lançada uma exceção ao chamar o método
getem umOptionalvazio.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalGetEmpty.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalGetEmpty.java[role=include]
Saída no consolevalor Exception in thread "main" java.util.NoSuchElementException: No value present at java.util.Optional.get(Optional.java:135) at org.j6toj8.lambda.builtininterfaces.BuiltInInterfaces_OptionalGetEmpty.main(BuiltInInterfaces_OptionalGetEmpty.java:13)
-
Existem algumas classes para lidar com valor opcionais de variáveis primitivas, já que elas não podem ser utilizada com
generics:OptionalInt,OptionalDouble,OptionalLong.src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalPrimitive.javalink:../../../src/org/j6toj8/lambda/builtininterfaces/BuiltInInterfaces_OptionalPrimitive.java[role=include]
Saída no console5
-
Working with Built-In Functional Interfaces
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide (p. 173). Wiley. Edição do Kindle.
-
Package java.util.function. Java Plataform SE 8.
-
Class Optional<T>. Java Plataform SE 8.