Second Lowest Number
second lowest number practice a focused java stream api coding question: second lowest number. solve it first with a stream pipeline, then
Introduction
Practice a focused Java Stream API coding question: Second Lowest Number. Solve it first with a stream pipeline, then compare it with the imperative alternative.
Purpose of this lesson
Build interview-ready Stream API muscle memory. Difficulty: Medium - XP: 50 - Estimated time: 10 min - Tags: distinct, sorted, optional.
Understanding the topic
Problem statement: Find the second lowest distinct number in a list.
Sample input: List.of(10, 5, 20, 5, 15)
Expected output: Optional[10]
Approach: Remove duplicates, sort ascending, skip the lowest, then take the next value.
Syntax reference
Stream solution:
Optional<Integer> secondLowest = numbers.stream().distinct().sorted().skip(1).findFirst();
Alternative solution:
Integer first = null, second = null;for (int n : new HashSet<>(numbers)) {if (first == null || n < first) {second = first;first = n;} else if (second == null || n < second) {second = n;}}Optional<Integer> result = Optional.ofNullable(second);
Informative example
Dry run: Distinct values are 10, 5, 20, 15; ascending order is 5, 10, 15, 20; skipping 5 returns 10.
- Follow-up: Can this be done in one pass?
- Follow-up: What should happen when all values are equal?
Complexity analysis
- Time: O(n log n)
- Space: O(n)
Real-world use
Interactive challenge: complete the starter code, then compare with the reference solution.
static Object solve(List<?> input) {// TODO: write the Stream pipelinereturn null;}
Reference solution:
Optional<Integer> secondLowest = numbers.stream().distinct().sorted().skip(1).findFirst();
Hints:
- Start with the operation that changes the number of elements.
- Use a terminal operation that returns exactly the expected output type.
- Write an empty-list test before the happy path.
Best practices
- Name the terminal operation and explain why it ends the pipeline.
- Mention how nulls, empty inputs, duplicates, and ordering affect the answer.
- State when a loop is clearer than a Stream pipeline.
Common mistakes
- Calling
get()on an emptyOptionalinstead of handling absence. - Using
sorted()for a problem that only needs one pass. - Mutating external state inside
map,filter, orforEach.
Debugging tips
- Print the intermediate result after each pipeline stage when the output surprises you.
- Temporarily replace method references with lambdas so you can inspect parameter names and values.
Optimization strategies
- Avoid unnecessary
distinct(),sorted(), and boxing on hot paths. - Use primitive streams such as
mapToIntwhen aggregating large numeric collections.
Advanced interview questions
Interview Prep
Practice concise answers, then expand each card for the explanation.
1QuestionCan this be done in one pass?+
Answer
2QuestionWhat should happen when all values are equal?+
Answer
Hands-on exercise
Practice progress metadata: difficulty=Medium, xp=50, estimatedTime=10 min, tags=distinct, sorted, optional.
Summary
You solved Second Lowest Number with Streams, compared it against an imperative alternative, reviewed complexity, and captured interview follow-ups.
Purpose of this lesson
Practice Stream API interview questions with production-style trade-offs, not just syntax recall.
Step-by-step explanation
- State the input, output, and edge cases before writing the pipeline.
- Choose the smallest useful Stream operation: filter, map, flatMap, reduce, or collect.
- Compare the Stream answer with the imperative alternative and explain readability trade-offs.
- Check performance notes: stateful operations, boxing, sorting, distinct, and parallel overhead.
Interactive workflow diagram
Identify use case
Recognize when second lowest number is the right tool for the problem.
Debugging tips
- Insert a temporary
peek()only while debugging, then remove it before committing. - If the result is missing rows, inspect every predicate in
filter()with a small sample input. - When collectors produce unexpected maps, print the classifier key for each element.
- When NOT to use Streams: complex branching, heavy mutation, tiny hot loops, or code where a clear loop is easier to review.
Optimization strategies
- Why
distinct()can be expensive: it keeps a set of seen values and depends on correctequals/hashCode. - When parallel streams hurt performance: small data, blocking I/O, shared mutable state, or expensive splitting.
- Common mistakes with
reduce(): non-neutral identity values and non-associative accumulators break parallel correctness. - Stream pipeline optimization: filter early, avoid intermediate collections, prefer primitive streams for numeric aggregation.
Enterprise example
Teams at Netflix, Uber and Goldman Sachs apply Second Lowest Number daily — usually wrapped behind Spring Boot services with observability hooks (Micrometer + OpenTelemetry).
Interview questions & answers
Q1What interview insight should you mention for this Stream problem?
Q2What alternative approach should you compare against?
Q3What performance note matters most?
sorted() and distinct(), plus the overhead of boxing and parallel execution.Summary
Use this question to practice both coding and explanation: the strongest interview answers include edge cases, trade-offs, and when not to use Streams.