ZetCode

Identity Function in Java Streams

last modified May 25, 2025

The identity function is a fundamental concept in functional programming that plays an important role in Java Stream operations. This tutorial explains its purpose and demonstrates practical use cases.

Function.identity is a static method in Java's java.util.function.Function interface that returns a function which always returns its input argument. It's essentially a no-op function that can be useful in various stream operations where a function parameter is required but no transformation is needed.

The identity function is particularly useful with Stream operations like map and collect where you need to pass a function but don't want to modify the elements. It serves as a clean, readable way to express "no transformation" in functional pipelines.

Basic Identity Function Usage

This example demonstrates the simplest use of Function.identity in a stream pipeline.

Main.java
void main() {

    Stream.of("apple", "banana", "cherry")
            .map(Function.identity())
            // .map(e -> e)
            .forEach(System.out::println);
}

Here we use Function.identity as the mapping function, which results in no change to the stream elements. While this example doesn't transform the data, it shows the basic syntax and behavior of the identity function.

The syntax of the Function.identity is equivalent to using a e -> e lambda expression, but using Function.identity is more concise and expressive.

$ java Main.java
apple
banana
cherry

Identity in Collectors.toMap

One of the most common uses of Function.identity is with Collectors.toMap when you want to use the stream elements as map keys.

Main.java
void main() {
    
    List<String> fruits = List.of("apple", "banana", "cherry");
    
    Map<String, Integer> fruitMap = fruits.stream()
        .collect(Collectors.toMap(
            Function.identity(),  // Use the string as key
            String::length        // Use length as value
        ));
    
    System.out.println(fruitMap);
}

In this example, we create a map where the keys are the fruit names (unchanged, thanks to Function.identity) and the values are the lengths of the fruit names. The identity function clearly expresses that we're using the original elements as keys.

$ java Main.java
{banana=6, apple=5, cherry=6}

Identity vs Lambda Expression

This example compares using Function.identity with an equivalent lambda expression to demonstrate their equivalence.

Main.java
void main() {
    
    // Using Function.identity()
    Stream.of(1, 2, 3)
          .map(Function.identity())
          .forEach(System.out::println);
    
    // Using equivalent lambda Stream.of(1, 2, 3).map(x -> x)
    //.forEach(System.out::println); 
}

Both versions produce identical results. Function.identity is generally preferred as it's more explicit about the intent and may have slight performance benefits in some cases as it's a singleton function.

$ java Main.java
1
2
3
1
2
3

Identity in GroupingBy

The identity function is often used with Collectors.groupingBy when you want to group by the elements themselves.

Main.java
void main() {
    
    List<String> words = List.of("one", "two", "three", "one", "three");
    
    Map<String, Long> counts = words.stream()
        .collect(Collectors.groupingBy(
            Function.identity(),
            Collectors.counting()
        ));
    
    System.out.println(counts);
}

Here we use Function.identity as the classifier function for grouping, which means we're grouping by the actual string values. This produces a frequency count of each word in the list.

$ java Main.java
{one=2, two=1, three=2}

Identity with Optional

The identity function can be useful when working with Optional in stream operations.

Main.java
void main() {

    List<Optional<String>> optionals = List.of(
            Optional.of("🍎 Apple"),
            Optional.empty(),
            Optional.of("🍌 Banana"),
            Optional.of("🍒 Cherry"),
            Optional.empty(),
            Optional.of("🍍 Pineapple"));

    // Extract present values without transformation
    List<String> values = optionals.stream()
            .flatMap(opt -> opt.map(Function.identity()).stream())
            .collect(Collectors.toList());

    System.out.println(values);
}

This example demonstrates using Function.identity to process a stream of Optional values, extracting the values when present without transforming them.

$ java Main.java
[🍎 Apple, 🍌 Banana, 🍒 Cherry, 🍍 Pineapple]

Source

Java Function.identity() Documentation

The identity function is a simple but powerful tool in Java Streams that clearly expresses the intent of "no transformation" in functional pipelines. While it doesn't modify data, it serves important roles in stream operations that require function parameters.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Java tutorials.