Função: Transformação de Dados
Enquanto Predicate nos ajuda a avaliar expressões booleanas, Function permite transformar dados aplicando operações que retornam resultados com base na entrada.
Function é comumente utilizado para transformação de dados, como conversão de tipo, cálculos ou processamento de valores.
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
A interface Function<T, R> em Java representa uma interface funcional que recebe um argumento do tipo T e retorna um resultado do tipo R.
O método apply(T t) realiza a transformação de dados ao receber o valor de entrada e retornar o resultado. Isso permite criar funções flexíveis para processar dados de diversos tipos.
Aplicação Prática
Suponha que você tenha uma lista de nomes de usuários e precise calcular o comprimento de cada nome para posterior análise ou processamento de dados.
Main.java
1234567891011121314151617package com.example; import java.util.Arrays; import java.util.List; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Alice", "Bob", "Charlie", "David"); Function<String, Integer> nameLength = name -> name.length(); users.forEach(user -> { System.out.println(user + " has " + nameLength.apply(user) + " characters."); }); } }
Neste exemplo, há uma lista de nomes de usuários. Para cada nome, utiliza-se a função nameLength, que calcula o número de caracteres no nome utilizando o método length(). Com o método forEach, é feita a iteração sobre cada elemento da lista e exibida uma mensagem mostrando quantos caracteres cada nome contém.
Combinando Funções
A interface Function oferece vários métodos para combinar funções, permitindo criar uma cadeia de operações.
Método andThen()
O método andThen() permite combinar duas funções aplicando uma função primeiro e, em seguida, passando o resultado para a segunda função. Isso é útil quando é necessário realizar múltiplas operações em sequência.
Exemplo
Você possui uma lista de nomes de usuários e precisa capitalizar a primeira letra de cada nome e, em seguida, verificar se o nome possui mais de 5 caracteres.
Main.java
1234567891011121314151617181920212223package com.example; import java.util.Arrays; import java.util.List; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> usernames = Arrays.asList("john", "alice", "bob", "charlie", "david"); // Capitalize first letter Function<String, String> capitalizeFirstLetter = name -> name.substring(0, 1).toUpperCase() + name.substring(1); // Check if the username has more than 5 characters Function<String, Boolean> isLongerThanFive = name -> name.length() > 5; // Combine functions using `andThen()` Function<String, Boolean> formattedNameThenCheckLength = capitalizeFirstLetter.andThen(isLongerThanFive); usernames.forEach(user -> { System.out.println(user + " -> " + formattedNameThenCheckLength.apply(user)); }); } }
Primeiro, capitalize a primeira letra de cada nome de usuário utilizando capitalizeFirstLetter. Em seguida, verifique se o nome formatado possui mais de 5 caracteres utilizando isLongerThanFive. As duas funções são combinadas usando andThen() para processamento sequencial.
Método compose()
O método compose() permite combinar funções, mas na ordem inversa: a segunda função é aplicada primeiro, e o resultado é então passado para a primeira função.
Exemplo
Você possui uma string e deseja primeiro calcular seu comprimento e depois adicionar um prefixo ao resultado.
Main.java
123456789101112131415161718package com.example; import java.util.function.Function; public class Main { public static void main(String[] args) { String phrase = "Hello World"; // First, calculate the length, then add a prefix Function<String, Integer> stringLength = String::length; Function<Integer, String> addPrefix = length -> "Length: " + length; // Combine functions using compose Function<String, String> lengthThenPrefix = addPrefix.compose(stringLength); System.out.println(lengthThenPrefix.apply(phrase)); // Output: Length: 11 } }
Neste exemplo, primeiro você calcula o comprimento da string usando stringLength, e então o resultado é passado para a função addPrefix, que adiciona um prefixo. Você utiliza compose() para aplicar as funções na ordem desejada.
Método identity()
O método identity() retorna uma função que simplesmente retorna seu argumento sem qualquer modificação. Isso é útil quando é necessário passar uma função que não altera o valor de entrada, mas é exigida para cumprir a interface.
Exemplo
Imagine que seja necessário processar uma lista de nomes de usuário aplicando várias transformações: uma para converter os nomes para maiúsculas, outra para adicionar o sufixo "User", e uma terceira utilizando a função identity() para deixar o nome inalterado. O objetivo é aplicar essas funções a cada nome da lista mantendo a interface do programa consistente para cada transformação.
Main.java
1234567891011121314151617181920212223242526272829303132package com.example; import java.util.List; import java.util.Arrays; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> usernames = Arrays.asList("alice", "bob", "charlie", "david", "eve"); // `Function` to convert the username to uppercase Function<String, String> uppercaseFunction = name -> name.toUpperCase(); // `Function` to add the "User" suffix Function<String, String> suffixFunction = name -> name + "User"; // Identity `Function`, which does nothing Function<String, String> identityFunction = Function.identity(); // Applying a combination of functions List<Function<String, ?>> transformations = Arrays.asList(uppercaseFunction, suffixFunction, identityFunction); // Applying each `Function` from the list for (Function<String, ?> transformation : transformations) { System.out.println("--------------------"); usernames.stream() .map(name -> transformation.apply(name)) .forEach(System.out::println); } } }
Como pode ser observado, a saída consiste em três listas formatadas de nomes de usuário. A última lista contém os nomes originais, onde o método identity() é útil, pois permite retornar os nomes sem adicionar lógica extra para tratar os valores inalterados. Isso torna o código mais limpo e eficiente ao utilizar diretamente o identity() quando nenhuma transformação é necessária.
1. O que o método andThen() na interface Function faz?
2. Qual será o resultado ao aplicar o método identity()?
3. O que o método compose() faz?
Obrigado pelo seu feedback!
Pergunte à IA
Pergunte à IA
Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo
Awesome!
Completion rate improved to 2.33
Função: Transformação de Dados
Deslize para mostrar o menu
Enquanto Predicate nos ajuda a avaliar expressões booleanas, Function permite transformar dados aplicando operações que retornam resultados com base na entrada.
Function é comumente utilizado para transformação de dados, como conversão de tipo, cálculos ou processamento de valores.
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
A interface Function<T, R> em Java representa uma interface funcional que recebe um argumento do tipo T e retorna um resultado do tipo R.
O método apply(T t) realiza a transformação de dados ao receber o valor de entrada e retornar o resultado. Isso permite criar funções flexíveis para processar dados de diversos tipos.
Aplicação Prática
Suponha que você tenha uma lista de nomes de usuários e precise calcular o comprimento de cada nome para posterior análise ou processamento de dados.
Main.java
1234567891011121314151617package com.example; import java.util.Arrays; import java.util.List; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Alice", "Bob", "Charlie", "David"); Function<String, Integer> nameLength = name -> name.length(); users.forEach(user -> { System.out.println(user + " has " + nameLength.apply(user) + " characters."); }); } }
Neste exemplo, há uma lista de nomes de usuários. Para cada nome, utiliza-se a função nameLength, que calcula o número de caracteres no nome utilizando o método length(). Com o método forEach, é feita a iteração sobre cada elemento da lista e exibida uma mensagem mostrando quantos caracteres cada nome contém.
Combinando Funções
A interface Function oferece vários métodos para combinar funções, permitindo criar uma cadeia de operações.
Método andThen()
O método andThen() permite combinar duas funções aplicando uma função primeiro e, em seguida, passando o resultado para a segunda função. Isso é útil quando é necessário realizar múltiplas operações em sequência.
Exemplo
Você possui uma lista de nomes de usuários e precisa capitalizar a primeira letra de cada nome e, em seguida, verificar se o nome possui mais de 5 caracteres.
Main.java
1234567891011121314151617181920212223package com.example; import java.util.Arrays; import java.util.List; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> usernames = Arrays.asList("john", "alice", "bob", "charlie", "david"); // Capitalize first letter Function<String, String> capitalizeFirstLetter = name -> name.substring(0, 1).toUpperCase() + name.substring(1); // Check if the username has more than 5 characters Function<String, Boolean> isLongerThanFive = name -> name.length() > 5; // Combine functions using `andThen()` Function<String, Boolean> formattedNameThenCheckLength = capitalizeFirstLetter.andThen(isLongerThanFive); usernames.forEach(user -> { System.out.println(user + " -> " + formattedNameThenCheckLength.apply(user)); }); } }
Primeiro, capitalize a primeira letra de cada nome de usuário utilizando capitalizeFirstLetter. Em seguida, verifique se o nome formatado possui mais de 5 caracteres utilizando isLongerThanFive. As duas funções são combinadas usando andThen() para processamento sequencial.
Método compose()
O método compose() permite combinar funções, mas na ordem inversa: a segunda função é aplicada primeiro, e o resultado é então passado para a primeira função.
Exemplo
Você possui uma string e deseja primeiro calcular seu comprimento e depois adicionar um prefixo ao resultado.
Main.java
123456789101112131415161718package com.example; import java.util.function.Function; public class Main { public static void main(String[] args) { String phrase = "Hello World"; // First, calculate the length, then add a prefix Function<String, Integer> stringLength = String::length; Function<Integer, String> addPrefix = length -> "Length: " + length; // Combine functions using compose Function<String, String> lengthThenPrefix = addPrefix.compose(stringLength); System.out.println(lengthThenPrefix.apply(phrase)); // Output: Length: 11 } }
Neste exemplo, primeiro você calcula o comprimento da string usando stringLength, e então o resultado é passado para a função addPrefix, que adiciona um prefixo. Você utiliza compose() para aplicar as funções na ordem desejada.
Método identity()
O método identity() retorna uma função que simplesmente retorna seu argumento sem qualquer modificação. Isso é útil quando é necessário passar uma função que não altera o valor de entrada, mas é exigida para cumprir a interface.
Exemplo
Imagine que seja necessário processar uma lista de nomes de usuário aplicando várias transformações: uma para converter os nomes para maiúsculas, outra para adicionar o sufixo "User", e uma terceira utilizando a função identity() para deixar o nome inalterado. O objetivo é aplicar essas funções a cada nome da lista mantendo a interface do programa consistente para cada transformação.
Main.java
1234567891011121314151617181920212223242526272829303132package com.example; import java.util.List; import java.util.Arrays; import java.util.function.Function; public class Main { public static void main(String[] args) { List<String> usernames = Arrays.asList("alice", "bob", "charlie", "david", "eve"); // `Function` to convert the username to uppercase Function<String, String> uppercaseFunction = name -> name.toUpperCase(); // `Function` to add the "User" suffix Function<String, String> suffixFunction = name -> name + "User"; // Identity `Function`, which does nothing Function<String, String> identityFunction = Function.identity(); // Applying a combination of functions List<Function<String, ?>> transformations = Arrays.asList(uppercaseFunction, suffixFunction, identityFunction); // Applying each `Function` from the list for (Function<String, ?> transformation : transformations) { System.out.println("--------------------"); usernames.stream() .map(name -> transformation.apply(name)) .forEach(System.out::println); } } }
Como pode ser observado, a saída consiste em três listas formatadas de nomes de usuário. A última lista contém os nomes originais, onde o método identity() é útil, pois permite retornar os nomes sem adicionar lógica extra para tratar os valores inalterados. Isso torna o código mais limpo e eficiente ao utilizar diretamente o identity() quando nenhuma transformação é necessária.
1. O que o método andThen() na interface Function faz?
2. Qual será o resultado ao aplicar o método identity()?
3. O que o método compose() faz?
Obrigado pelo seu feedback!