Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Function: Data Transformation | Fundamentals and Functional Capabilities of Stream API
Stream API
course content

Course Content

Stream API

Stream API

1. Fundamentals and Functional Capabilities of Stream API
4. Practical Applications of Stream API

book
Function: Data Transformation

While Predicate helps us evaluate boolean expressions, Function allows us to transform data by applying operations that return results based on the input.

Function is commonly used for data transformation, such as type conversion, calculations, or value processing.

The Function<T, R> interface in Java represents a functional interface that takes an argument of type T and returns a result of type R.

The apply(T t) method performs the data transformation by taking the input value and returning the result. This allows for creating flexible functions to process data of various types.

Practical Application

Let's say you have a list of user names, and you need to calculate the length of each name for further analysis or data processing.

java

Main

copy
1234567891011121314151617
package 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."); }); } }

In this example, you have a list of user names. For each name, you use the nameLength function, which calculates the number of characters in the name using the length() method. Using the forEach method, you iterate over each element of the list and print a message showing how many characters each name contains.

Combining Functions

The Function interface provides several methods for combining functions, allowing you to create a chain of operations.

Method andThen()

The andThen() method allows you to combine two functions by applying one function first, then passing the result to the second function. This is useful when you need to perform multiple operations in sequence.

Example

You have a list of user names, and you need to capitalize the first letter of each name and then check if the name has more than 5 characters.

java

Main

copy
1234567891011121314151617181920212223
package 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)); }); } }

You first capitalize the first letter of each username using capitalizeFirstLetter. Then, you check if the formatted username has more than 5 characters using isLongerThanFive. The two functions are combined using andThen() for sequential processing.

Method compose()

The compose() method allows you to combine functions, but in the reverse order: the second function is applied first, and the result is then passed into the first function.

Example

You have a string, and you want to first calculate its length and then prepend a prefix to the result.

java

Main

copy
123456789101112131415161718
package 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 } }

In this example, you first calculate the length of the string using stringLength, and then the result is passed to the addPrefix function, which prepends a prefix. You use compose() to apply the functions in the desired order.

Method identity()

The identity() method returns a function that simply returns its argument without any modifications. This is useful when you need to pass a function that doesn't change the input value but is required to comply with the interface.

Example

Imagine you need to process a list of usernames by applying several transformations: one to convert the names to uppercase, another to add the "User" suffix, and a third using the identity() function to leave the name unchanged. The task is to apply these functions to each name in the list while keeping the program's interface consistent for each transformation.

java

Main

copy
1234567891011121314151617181920212223242526272829303132
package 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); } } }

As you can see, the output consists of three formatted lists of usernames. The last list contains the original names, which is where the identity() method comes in handy, as it allows us to return the names without adding extra logic for handling the unchanged values. This makes the code cleaner and more efficient by directly using identity() when no transformation is needed.

1. What does the andThen() method in the Function interface do?

2. What will be the result when applying the identity() method?

3. What does the compose() method do?

question mark

What does the andThen() method in the Function interface do?

Select the correct answer

question mark

What will be the result when applying the identity() method?

Select the correct answer

question mark

What does the compose() method do?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

Section 1. Chapter 6
We're sorry to hear that something went wrong. What happened?
some-alt