Back to Stream: map & Transform
Q9Question 9 of 34

Write a Function<Employee, String> that extracts the name, then compose with andThen(String::toUpperCase)

Key Concepts
  • Function<T, R>.andThen(after) chains two functions: run the first, then feed its result to the second
  • f.andThen(g) runs f first then g; f.compose(g) runs g first then f
  • The composed function is itself a Function, usable anywhere one is expected
  • Composition builds pipelines of small, testable transformations instead of one big lambda
  • Types must align: the output of the first function must match the input of the second
  • Guard against null intermediate values if the first function can return null

Definition

andThen chains functions left to right: extract the name, then uppercase it.
  • Function maps an input to an output.
  • .andThen(after) composes two functions so the first runs and its result feeds the second.
  • f.andThen(g) runs f first, then g. f.compose(g) runs g first, then f.
  • The composed function is itself a Function, usable in map() and other APIs.
  • Types must align: the output of the first function must match the input of the second.

Priya at the National Bank of India first pulls the name off an employee file, then runs that name through a capitaliser. Two steps on an assembly line: get the name, then make it uppercase.

Understanding the Concepts

How do you compose two functions with andThen?

Define the first function, call andThen with the second, and the result is a single composed function.

JAVA
package com.bank.hr;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FunctionComposition {
    public static void main(String[] args) {
        List<Employee> employees = List.of(
            new Employee("Rajesh", "Loans"),
            new Employee("Priya",  "IT"),
            new Employee("Amit",   "Finance")
        );

        Function<Employee, String> getName = Employee::getName;
        Function<Employee, String> getUpperName =
            getName.andThen(String::toUpperCase);

        List<String> upperNames = employees.stream()
            .map(getUpperName)
            .collect(Collectors.toList());

        System.out.println(upperNames);
    }
}
TEXT
[RAJESH, PRIYA, AMIT]

What is the difference between andThen and compose?

| Method | Execution order | Read as |
|---|---|---|
| f.andThen(g) | f first, then g | "f and then g" |
| f.compose(g) | g first, then f | "f after g" |

JAVA
Function<String, String> trim = String::trim;
Function<String, String> upper = String::toUpperCase;

// andThen: trim first, then uppercase
String result1 = trim.andThen(upper).apply("  hello  ");
// "HELLO"

// compose: uppercase first, then trim
String result2 = trim.compose(upper).apply("  hello  ");
// "HELLO" (same here, but order matters for other functions)

How do you chain more than two functions?

JAVA
Function<Employee, String> pipeline =
    ((Function<Employee, String>) Employee::getName)
        .andThen(String::trim)
        .andThen(String::toUpperCase);

// Applied in order: getName → trim → toUpperCase

What are common mistakes?

Mistake: null intermediate value causing NullPointerException.

JAVA
// WRONG: if getName returns null, toUpperCase throws NPE
Function<Employee, String> unsafe =
    ((Function<Employee, String>) Employee::getName)
        .andThen(String::toUpperCase);

// CORRECT: guard with a null-safe step
Function<Employee, String> safe =
    ((Function<Employee, String>) Employee::getName)
        .andThen(name -> name != null ? name.toUpperCase() : "UNKNOWN");

What should a senior engineer know?

  • Composition builds a pipeline of small, individually testable transformations.
  • andThen reads naturally left to right, matching the data flow direction.
  • The composed function is a new Function instance; the originals are unchanged.
  • For more complex pipelines, consider a dedicated method or class rather than long chains.

What are common interview follow-up questions?

  • "Can you compose with a Predicate?" Not directly; Predicate has and/or/negate, not andThen. Convert to a Function if needed.
  • "What about Function.identity()?" Returns a function that returns its input unchanged, useful as a default.
  • "Can you compose BiFunction?" BiFunction has andThen (for the result) but not compose.

Visual Overview

DIAGRAM
  Employee("Rajesh")
       │
       │  getName
       ▼
  "Rajesh"
       │
       │  toUpperCase (andThen)
       ▼
  "RAJESH"

  Pipeline: Employee → getName → toUpperCase → String

Key Takeaway

Function.andThen chains two functions left to right: the first function runs, and its result feeds into the second. Define getName as a Function, call andThen(String::toUpperCase), and you get a single composed function that extracts the name and uppercases it.

The composed function is itself a Function, so pass it directly to map() in a stream. At the National Bank of India, the uppercase-name report used this composition instead of writing one large lambda.

Composition builds pipelines of small, testable transformations. Types must align: the output of the first function must match the input of the second. Guard against null intermediate values to prevent NPE.

Remember one sentence: f.andThen(g) runs f first then g, composing small functions into a readable pipeline.

---

Share
Use ← → arrow keys to navigate