Back to Functional Interfaces
Q9Question 9 of 13

Write a Supplier<Employee> that creates a default employee

Key Concepts
  • Supplier<T> takes no input and returns a value from its get() method
  • Laziness is the key benefit: the object is created only when get() is called
  • orElseGet(supplier) calls the supplier only when the Optional is empty (lazy)
  • orElse(value) always evaluates its argument even when the Optional has a value (eager)
  • Stream.generate(supplier) produces an infinite stream of values from a supplier
  • Use Supplier to defer expensive or side-effecting construction

Definition

Supplier<Employee> takes nothing and returns a fresh Employee from get(): perfect for lazy defaults.
  • Supplier has a single get() method taking no input and returning a value.
  • Laziness: the object is built only when get() is called, not when the Supplier is defined.
  • orElseGet(supplier) defers construction to the empty case.
  • orElse(value) eagerly evaluates the default even when unused.
  • Stream.generate(supplier) produces values on demand.

Priya at the National Bank of India keeps a stamp that prints a blank default employee form on demand. Whenever she needs one, she presses the stamp. No inputs needed, out comes a fresh default.

Understanding the Concepts

How do you define a Supplier?

A Supplier has no arguments and returns a value each time get() is called.

JAVA
package com.bank.hr;

import java.util.function.Supplier;
import java.util.Optional;

public class SupplierDemo {
    public static void main(String[] args) {
        Supplier<Employee> defaultEmployee =
            () -> new Employee("UNKNOWN", "Unassigned", 0.0);

        // Called only when needed
        Employee e = defaultEmployee.get();
        System.out.println(e.getName()); // UNKNOWN

        // Used with Optional.orElseGet
        Optional<Employee> empty = Optional.empty();
        Employee fallback = empty.orElseGet(defaultEmployee);
        System.out.println(fallback.getName()); // UNKNOWN
    }
}
TEXT
UNKNOWN
UNKNOWN

What is the difference between orElse and orElseGet?

| Method | When default is evaluated | Use when |
|---|---|---|
| orElse(value) | Always, even when Optional has a value | Default is cheap and pre-computed |
| orElseGet(supplier) | Only when Optional is empty | Default is expensive or has side-effects |

JAVA
// WRONG: expensive default created even when not needed
Optional<Employee> present = Optional.of(existingEmployee);
Employee e1 = present.orElse(expensiveDbLookup());
// expensiveDbLookup() was called for nothing!

// CORRECT: lazy evaluation
Employee e2 = present.orElseGet(() -> expensiveDbLookup());
// expensiveDbLookup() is NOT called because present has a value

How do you use Supplier with Stream.generate?

JAVA
import java.util.stream.Stream;

// Generate 5 default employees
Stream.generate(defaultEmployee)
    .limit(5)
    .forEach(e -> System.out.println(e.getName()));
TEXT
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN
UNKNOWN

What are common mistakes?

Mistake: confusing orElse with orElseGet.

JAVA
// Both return the same result, but orElse always evaluates the argument:
Optional<Employee> opt = Optional.of(employee);
opt.orElse(new Employee("Default"));       // Employee created, then discarded
opt.orElseGet(() -> new Employee("Default")); // Lambda never called

What about BooleanSupplier and other specialised suppliers?

Java provides specialised suppliers for primitives to avoid boxing.

JAVA
import java.util.function.IntSupplier;

IntSupplier accountCounter = () -> 1001; // no boxing
int id = accountCounter.getAsInt();

What should a senior engineer know?

  • Supplier defers construction: you pay the cost only when the value is consumed.
  • Use supplier-form logging (log.info(() -> msg)) so the message string is assembled only when the level is enabled.
  • Supplier is commonly used in collector factories, map computation (computeIfAbsent), and lazy initialization.
  • A Supplier can return a different value on each call (new object) or always the same (cached value).

What are common interview follow-up questions?

  • "What is the difference between Supplier and Callable?" Callable can throw checked exceptions; Supplier cannot.
  • "Can a Supplier take arguments?" No; use Function for one argument or BiFunction for two.
  • "How do you create a Supplier from a constructor?" Employee::new serves as Supplier when matching the no-arg constructor.

Visual Overview

DIAGRAM
  Supplier<Employee>  () -> new Employee("UNKNOWN")

  Not called yet → no object created

  Optional.empty()
       │
       │  .orElseGet(supplier)
       │  Optional is empty → call supplier.get()
       ▼
  new Employee("UNKNOWN")  ← created on demand

  Optional.of(existing)
       │
       │  .orElseGet(supplier)
       │  Optional has value → supplier NOT called
       ▼
  existing  ← supplier was never invoked

Key Takeaway

A Supplier is a functional interface with a no-argument get() method that returns a value. Its key benefit is laziness: the value is created only when get() is called, not when the Supplier is defined.

This is why orElseGet(supplier) is better than orElse(value) when the default is expensive: orElse always evaluates its argument, while orElseGet calls the supplier only when the Optional is empty. At the National Bank of India, the account lookup used orElseGet to avoid constructing a default employee object on every successful find.

Supplier is also the factory behind Stream.generate for on-demand value production and behind computeIfAbsent for lazy map population.

Remember one sentence: Supplier defers construction to when get() is called, and orElseGet uses that laziness to avoid building a default when the Optional already has a value.

---

Share
Use ← → arrow keys to navigate