distinct(), limit() and skip()
Removing duplicates, taking the first N, offsetting, pagination with skip + limit, order of operations and Nth-highest problems.
#Introduction
Three operations that appear in almost every real-world application:
- Removing duplicates (
distinct()) - Fetching the first N records (
limit()) - Pagination (
skip()+limit())
These are heavily used in Spring Boot APIs, reporting, dashboards and interview coding rounds. By the end of this chapter you'll master distinct(), limit(), skip(), pagination using Streams, Top-N and Bottom-N problems, and how the order of operations affects results and performance.
#distinct()
distinct() removes duplicate elements from a stream.
stream.distinct()It uses equals() and hashCode() to determine duplicates.
Remove Duplicate Integers
List<Integer> numbers = Arrays.asList(2, 5, 2, 8, 5, 10, 8);
numbers.stream()
.distinct()
.forEach(System.out::println);2
5
8
10Notice: the first occurrence is preserved and the encounter order remains the same.
Duplicate Strings
List<String> names = Arrays.asList("John", "Alex", "John", "Bob", "Alex");
names.stream()
.distinct()
.forEach(System.out::println);John
Alex
Bob#distinct() with Custom Objects
class Employee {
int id;
String name;
// equals()
// hashCode()
}
employees.stream()
.distinct()
.forEach(System.out::println);This works correctly only if equals() and hashCode() are implemented properly.
Common Interview Trap
Employee e1 = new Employee(1, "John");
Employee e2 = new Employee(1, "John");Without overriding equals() and hashCode(), distinct() outputs both objects:
John
JohnWhy? Because Java compares object references by default.
Correct Implementation
@Override
public boolean equals(Object obj) {
// compare id
}
@Override
public int hashCode() {
// hash id
}Now employees.stream().distinct() works correctly.
#limit()
Returns only the first N elements.
stream.limit(n)numbers.stream() // 2, 5, 2, 8, 5, 10, 8
.limit(3)
.forEach(System.out::println);2
5
2Only the first three elements are processed.
Top 5 Highest Salaries
employees.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.limit(5)
.forEach(System.out::println);A very common interview problem.
#skip()
Skips the first N elements.
stream.skip(n)numbers.stream() // 2, 5, 2, 8, 5, 10, 8
.skip(2)
.forEach(System.out::println);2
8
5
10
8The first two elements are ignored.
#skip() + limit() = Pagination
This is used everywhere. With page size = 10 and page number = 3:
skip = (pageNumber - 1) * pageSize
= (3 - 1) * 10
= 20employees.stream()
.skip(20)
.limit(10)
.toList();Exactly how pagination works conceptually.
Example
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
numbers.stream()
.skip(3)
.limit(4)
.forEach(System.out::println);4
5
6
7#Combining Operations
With numbers = [2, 5, 2, 8, 5, 10, 8]:
| Pipeline | Output |
|---|---|
.distinct().sorted() | 2, 5, 8, 10 |
.filter(n -> n % 2 == 0).distinct() | 2, 8, 10 |
.sorted(Comparator.reverseOrder()).limit(3) | 10, 8, 8 |
.distinct().sorted(Comparator.reverseOrder()).limit(3) | 10, 8, 5 — unique values |
#Order of Operations Matters
numbers.stream().limit(5).distinct();Now reverse it:
numbers.stream().distinct().limit(5);#Performance Tip
stream.sorted().limit(5)Java sorts every element before taking the first five. If your requirement allows it, filter early:
stream.filter(...).sorted().limit(5)Fewer elements to sort.
#Real Spring Boot Examples
// Latest 10 orders
orders.stream()
.sorted(Comparator.comparing(Order::getOrderDate).reversed())
.limit(10)
.toList();
// Second page of users
users.stream()
.skip(10)
.limit(10)
.toList();
// Unique product categories
products.stream()
.map(Product::getCategory)
.distinct()
.toList();
// Top 5 highest salaries
employees.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.limit(5)
.toList();#Interview Questions
Q1Is distinct() intermediate or terminal?
Intermediate (stateful).
Q2How does distinct() identify duplicates?
It relies on equals() and hashCode().
Q3Why isn't distinct() removing duplicate objects?
Because equals() and hashCode() are not overridden correctly.
Q4What is skip() mainly used for?
Pagination.
Q5Difference between limit() and skip()?
| limit() | skip() |
|---|---|
| Takes the first N elements | Ignores the first N elements |
| Restricts stream size | Offsets the stream |
#Interview Challenges
Q1Second highest unique salary
double secondHighest = employees.stream()
.map(Employee::getSalary)
.distinct()
.sorted(Comparator.reverseOrder())
.skip(1)
.findFirst()
.orElseThrow();Q2Third smallest unique number
int third = numbers.stream()
.distinct()
.sorted()
.skip(2)
.findFirst()
.orElseThrow();#Practice Problems
List<Integer> numbers = Arrays.asList(5, 2, 8, 2, 10, 5, 12, 8, 15, 20);- Remove duplicates.
- Print the first 5 numbers.
- Skip the first 3 numbers.
- Skip 2 and print the next 4.
- Sort ascending and print the first 3 numbers.
- Sort descending and print the top 5 numbers.
- Print the second highest unique number.
- Print the third smallest unique number.
- Remove duplicates, sort descending, and print the top 2.
- Count the number of unique elements.
class Employee {
int id;
String name;
String department;
double salary;
}- Print unique departments.
- Print the top 3 highest-paid employees.
- Print employees after skipping the first 5.
- Print employees 6–10.
- Print the second highest salary.
- Print the third highest salary.
- Print the top 5 unique salaries.
- Print employees after removing duplicate IDs (assume
equals()/hashCode()are implemented). - Sort by salary, skip the lowest 2, and print the next 3.
- Find the first employee after skipping the first 10.
#Senior Java Interview Tips
Q11. Know the execution order
stream
.filter(...)
.distinct()
.sorted()
.skip(5)
.limit(10)
.map(...)
.collect(...);is processed in the exact order you write it.
Q22. Use distinct() only when needed
It maintains state internally, so it has overhead. Avoid it if your data is already unique.
Q33. Prefer database pagination for large datasets
For millions of records, don't do this:
repository.findAll()
.stream()
.skip(100000)
.limit(20);Instead, let the database handle pagination (e.g. Spring Data Pageable) and stream only the required page.
#Chapter Summary
distinct()relies onequals()/hashCode()and keeps the first occurrencelimit()andskip()- Pagination with
skip()+limit() - Order of operations changes results
- Nth-highest / Nth-smallest patterns
- Database pagination for large datasets