Remove Duplicate Elements in Java
Problem
Removing duplicate elements means keeping only the first occurrence of each value and dropping every repeat, while preserving the original order.
Given an array of integers, remove every repeated element so each one appears only once, in its original order.
Java Program
import java.util.LinkedHashSet;
import java.util.Set;
public class RemoveDuplicateElements {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 3, 9, 5, 1};
Set<Integer> seen = new LinkedHashSet<>();
// add() silently ignores duplicates, and insertion order is preserved
for (int num : arr) {
seen.add(num);
}
StringBuilder result = new StringBuilder("[");
int i = 0;
for (int num : seen) {
if (i > 0) result.append(", ");
result.append(num);
i++;
}
result.append("]");
System.out.println(result);
}
}Output
Core Logic
A LinkedHashSet already keeps only unique elements while preserving the order they were added in — exactly what deduplication needs.
- 1A
LinkedHashSet<Integer>namedseentracks every distinct element encountered so far, in insertion order. - 2Adding an element that's already in the set has no effect —
Set.add()silently ignores duplicates. - 3After scanning the whole array once,
seenholds each element exactly once, in the order it first appeared. - 4
seen.stream().mapToInt(Integer::intValue).toArray()converts the set back into a plainint[]for printing.
[5, 3, 8, 3, 9, 5, 1], the repeated 3 and 5 are silently dropped, leaving [5, 3, 8, 9, 1].Key Point: A plain HashSet would also remove duplicates, but wouldn't guarantee the original order — LinkedHashSet is the one that keeps 'first occurrence' order intact.
Why: Each element is visited once, and the LinkedHashSet holds up to n distinct elements in the worst case.
Key Concepts
Approach 2: Manual Boolean Tracking
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class RemoveDuplicateElementsManual {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 3, 9, 5, 1};
Set<Integer> seen = new HashSet<>();
List<Integer> result = new ArrayList<>();
for (int num : arr) {
// add() returns true only the first time an element is added
if (seen.add(num)) {
result.add(num);
}
}
System.out.println(result);
}
}
Output
Core Logic
Set.add() already returns whether the element was new — checking that return value directly avoids a separate contains() lookup before adding.
- 1A
HashSet<Integer>namedseentracks which elements have already been added, and anArrayList<Integer>namedresultholds the deduplicated output in order. - 2
seen.add(num)both adds the element and returnstrueonly if it wasn't already present. - 3That single boolean result decides whether
numalso gets appended toresult. - 4Because
arris scanned in order,resultends up holding each distinct value in first-appearance order, same as the LinkedHashSet version.
[5, 3, 8, 3, 9, 5, 1], the second 3 and second 5 both cause seen.add() to return false, so neither is appended to result.Key Point: This uses a plain HashSet just for membership tracking and a separate ArrayList for ordering, rather than relying on LinkedHashSet to do both jobs at once.
Why: Both the HashSet and the ArrayList can hold up to n elements, so the extra memory still scales with the array's size.
Key Concepts
Approach 3: Java 8
import java.util.Arrays;
public class RemoveDuplicateElementsStream {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 3, 9, 5, 1};
// distinct() keeps only the first occurrence of each value, in encounter order
int[] result = Arrays.stream(arr).distinct().toArray();
System.out.println(Arrays.toString(result));
}
}
Output
Core Logic
distinct() already does exactly this — it keeps each stream element only the first time it appears, in encounter order.
- 1
Arrays.stream(arr)converts theint[]into anIntStream. - 2
.distinct()filters out every repeated value, keeping only the first occurrence of each, same as the LinkedHashSet version. - 3
.toArray()collects the deduplicated values back into a plainint[].
Arrays.stream(new int[]{5, 3, 8, 3, 9, 5, 1}).distinct() produces [5, 3, 8, 9, 1] in a single expression.Key Point: distinct() internally has to track every value it's already seen — the same underlying idea as the LinkedHashSet version, just built into the stream itself.
Why: distinct() tracks every element it's already seen internally, and the resulting array holds up to n distinct values.