Java Arrays and Collections: Sets, Lists and Duplicate Removal

A java set is a collection interface in java.util that stores only unique elements and automatically rejects duplicates at insertion. The three main implementations are HashSet (unordered, O(1) average), LinkedHashSet (insertion-ordered) and TreeSet (sorted, O(log n)). Use a java set whenever you need uniqueness without writing custom deduplication loops.

  • Key Takeaway 1: A HashSet gives O(1) average lookup and automatically removes duplicates, making it ideal for deduplication tasks.
  • Key Takeaway 2: Converting between a List and an array is a two-liner in Java using Arrays.asList() or toArray().
  • Key Takeaway 3: Fail-fast iterators throw ConcurrentModificationException the moment the collection changes; fail-safe iterators work on a copy and never throw it.
  • Key Takeaway 4: Sorting a 2D array in Java uses Arrays.sort() with a lambda comparator, not a simple one-liner sort call.
  • Key Takeaway 5: Java’s BitSet is a memory-efficient class that can remove duplicates from large integer arrays faster than a HashSet in many cases.

How the Java Set Interface Works (and When to Use It)

The Set interface sits inside the java.util package and extends Collection. Every class that implements a java set, whether HashSet, LinkedHashSet or TreeSet, enforces the no-duplicates rule at the point of insertion. You never need to check first; the add() method simply returns false if the element already exists. This makes a java set the cleanest tool for deduplication in any Java backend codebase.

According to the TIOBE Index (March 2025), Java remains the third most-used programming language globally. The JetBrains State of Developer Ecosystem 2024 report found that 60% of Java developers use the Collections Framework daily, and java set implementations appear in nearly every Java developer interview in India, from TCS and Infosys to product startups. Understanding the java set hierarchy is not optional for anyone targeting a backend role.

HashSet vs LinkedHashSet vs TreeSet: Java Set Implementations Compared

Java Set Implementation Order Guarantee Null Allowed Time Complexity (add/contains) Best Use Case
HashSet None Yes (one null) O(1) average Fast deduplication
LinkedHashSet Insertion order Yes (one null) O(1) average Ordered unique elements
TreeSet Sorted (natural or comparator) No O(log n) Sorted unique elements

Java Set vs List: Key Differences

A java set rejects duplicates automatically; a List allows them. A List maintains index-based access and guaranteed insertion order; a java set (except LinkedHashSet) does not. Use a java set when uniqueness is the requirement. Use a List when you need positional access or duplicate entries. The contains() method on a java set runs in O(1) for HashSet versus O(n) for an unsorted ArrayList, which matters at scale.

BitSet: The Underrated Option for Integer Deduplication

BitSet is a class in java.util that stores bits rather than objects. It is not part of the standard java set hierarchy, but it is useful when working with large arrays of non-negative integers. A BitSet of size 1,000,000 uses roughly 125 KB of memory, compared to a HashSet<Integer> that can consume several megabytes for the same range.

The pattern: set a bit at position i to mark that integer as seen, then iterate through the BitSet to reconstruct unique values.

BitSet bitSet = new BitSet();
for (int num : arr) {
    bitSet.set(num);
}
// Iterate bitSet.nextSetBit(0) to get unique values

This pattern appears in competitive programming and in screening rounds at companies like Amazon and Google during India’s campus hiring season.

Converting Between Lists and Arrays in Java

The confusion between List and array types trips up a surprising number of developers. According to the Stack Overflow Developer Survey 2024, Java ranks as the fifth most-used programming language among professional developers worldwide, and array and collection manipulation are consistently among the most-searched Java topics on the platform.

List to Array in Java

The cleanest way to convert a List<String> to a String[] is using the toArray() method with a typed array argument:

String[] arr = list.toArray(new String[0]);

Passing new String[0] is the modern, JVM-optimised pattern. Passing a pre-sized array used to be recommended, but benchmarks from the JetBrains IntelliJ team have shown the zero-length version performs equally well or better on modern JVMs.

Array to List in Java

Going the other direction uses Arrays.asList():

List<String> list = Arrays.asList(arr);

The list returned by Arrays.asList() is fixed-size. You can update existing elements, but calling add() or remove() throws an UnsupportedOperationException. If you need a fully mutable list, wrap it: new ArrayList<>(Arrays.asList(arr)).

Adding an Element to an Array in Java

Arrays in Java have a fixed length. The standard patterns are: create a new array one size larger and copy elements using System.arraycopy(), or use an ArrayList from the start and call toArray() only when you need the array form. For one-off additions, Arrays.copyOf(arr, arr.length + 1) is the shortest path.

If you’re building skills for a backend or full-stack role, understanding these array manipulation patterns is exactly the kind of practical knowledge listed in our guide to top skills every college student must learn before graduation.

Removing Duplicates from an Array in Java

There are three mainstream approaches to remove duplicates in array Java scenarios, each with a different trade-off between simplicity, performance and order preservation.

Method 1: Use a Java Set (HashSet)

Push all elements into a java set (HashSet), then convert back to an array. This is O(n) average time and two lines of code. Order is not preserved.

Set<Integer> set = new HashSet<>(Arrays.asList(arr));
Integer[] unique = set.toArray(new Integer[0]);

Method 2: Use a Java Set (LinkedHashSet) to Preserve Order

Same pattern, but swap HashSet for LinkedHashSet. You get O(n) time and insertion order is preserved. This java set approach is the go-to solution in most interview scenarios where order matters.

Set<Integer> set = new LinkedHashSet<>(Arrays.asList(arr));
Integer[] unique = set.toArray(new Integer[0]);

Method 3: Sort and Compare

Sort the array first using Arrays.sort(), then walk through comparing adjacent elements. This is O(n log n) and works on primitive arrays without boxing overhead. It is useful when you are already sorting for another reason and want to avoid the overhead of creating a java set object.

According to Naukri.com’s 2024 Java Developer Hiring Trends report, Java Collections knowledge, including java set usage and array deduplication, is listed as a required skill in over 70% of Java developer job postings in India across Bengaluru, Hyderabad and Pune. Knowing at least two deduplication methods fluently is a real competitive edge in the Indian IT job market.

Converting a String to a Character Array

A related pattern: converting a String to a character array for character-level processing. Java’s String.toCharArray() returns a char[]. For duplicate character removal, push the char[] into a LinkedHashSet<Character> and rebuild the string. This java set pattern appears in coding rounds at Wipro, HCL and Zoho, which are among the top hirers of fresh Java developers in India.

If you’re exploring what roles you can target with these skills, our breakdown of entry-level jobs for teens and fresh graduates is a useful read.

Fail-Fast vs Fail-Safe Iterators and Sorting 2D Arrays

These two topics appear together in Java interviews because they both reveal whether a candidate understands what happens under the hood when collections are modified during iteration.

Fail-Fast Iterators

A fail-fast iterator, used by ArrayList, HashSet, HashMap and most standard collections, monitors a structural modification counter called modCount. The moment you add or remove an element while iterating with a for-each loop or an explicit Iterator, it throws a ConcurrentModificationException. This is a design choice, not a bug. It tells you immediately that your code has a concurrency or logic problem.

Fail-Safe Iterators

Fail-safe iterators, found in ConcurrentHashMap, CopyOnWriteArrayList and other classes in the java.util.concurrent package, work on a snapshot copy of the collection. They never throw ConcurrentModificationException. The trade-off is that changes made after the iterator was created are not visible in the current iteration pass, and they consume more memory because of that copy.

According to the Oracle Java SE 21 documentation, fail-safe behaviour is explicitly the design goal of all classes in the java.util.concurrent package, making them the right choice for multi-threaded environments.

Feature Fail-Fast Fail-Safe
Exception on modification Yes (ConcurrentModificationException) No
Works on original collection Yes No (works on copy)
Memory overhead Low Higher
Thread-safe iteration No Yes
Examples ArrayList, HashSet, HashMap ConcurrentHashMap, CopyOnWriteArrayList

How to Sort a 2D Array in Java

Sorting a 2D array is not as straightforward as a 1D sort. Arrays.sort() does not sort a 2D array by default; you need a comparator. The most common pattern is sorting by a specific column.

To sort a 2D int array by the first column in ascending order:

Arrays.sort(matrix, (a, b) -> a[0] - b[0]);

To sort by the second column in descending order:

Arrays.sort(matrix, (a, b) -> b[1] - a[1]);

This uses a lambda comparator passed to Arrays.sort(). Java treats each row of a 2D array as a 1D array, so the comparator compares two int[] rows. This pattern appears in interval scheduling, meeting rooms and activity selection problems, all common in FAANG-style interviews on LeetCode and HackerRank.

Getting these fundamentals right opens doors to higher-paying roles. If you’re thinking about which direction to go, our guide on best career options in 2026 for students and professionals covers roles where Java skills command strong salaries in India’s IT market.

If you’re weighing your options post-graduation, the advice in our career path guide for 2026 graduates is worth 15 minutes of your time.

For structured learning, the top online courses for high-salary jobs and best free online learning platforms for students pages on 3University will help you find the right course to go deeper on Java and data structures. Browse the full range of certification courses at 3University to find structured programmes in Cybersecurity, Ethical Hacking, AI, Blockchain and Web3 that pair well with your Java foundation.

Frequently Asked Questions

What is a java set?

A java set is a collection interface in java.util that stores only unique elements. It is part of the Java Collections Framework. The main java set implementations are HashSet (unordered, fastest), LinkedHashSet (insertion-ordered) and TreeSet (sorted). A java set automatically rejects duplicate entries; the add() method returns false if the element already exists.

What is the difference between a java set and a List?

A java set does not allow duplicate elements and does not guarantee index-based access. A List allows duplicates and maintains positional order. Use a java set when uniqueness is required. Use a List when you need to access elements by index or allow repeated values. The contains() check on a HashSet runs in O(1) versus O(n) on an unsorted ArrayList.

How do you convert a List to an array in Java?

Use the toArray() method on the List object. The recommended pattern is list.toArray(new String[0]) for a List<String>. Passing a zero-length typed array lets the JVM optimise allocation. To go the other way, use Arrays.asList(arr), but remember the resulting list is fixed-size and will not support add() or remove().

How do you remove duplicates from an array in Java?

The fastest approach is to pass the array into a java set (HashSet) via Arrays.asList(), then call toArray(). If you need to preserve insertion order, use LinkedHashSet instead. For primitive arrays without boxing, sort the array first with Arrays.sort() and then walk through comparing adjacent elements to filter out duplicates in O(n log n) time.

What is the difference between fail-fast and fail-safe iterators?

Fail-fast iterators (used by ArrayList, HashSet) throw ConcurrentModificationException if the collection is modified during iteration. Fail-safe iterators (used by ConcurrentHashMap, CopyOnWriteArrayList) operate on a copy of the collection, so they never throw that exception. Fail-safe iterators use more memory and will not reflect changes made after the iterator was created.

How do you sort a 2D array in Java?

Use Arrays.sort() with a lambda comparator. For example, to sort a 2D int array by the first column: Arrays.sort(matrix, (a, b) -> a[0] - b[0]);. Each row is treated as a 1D int[], so the comparator receives two rows and compares the chosen column’s values. Reverse the subtraction to sort in descending order.

How do you add an element to an array in Java?

Arrays in Java are fixed-length, so you cannot add an element directly. The standard approach is to use Arrays.copyOf(arr, arr.length + 1) to create a new array one element larger, then assign the new value to the last index. Alternatively, use an ArrayList throughout and call toArray() only when the array form is needed.

Last updated: June 2025. Reviewed by the 3University editorial team.

We create, review, and maintain educational content covering Cybersecurity, Ethical Hacking, Artificial Intelligence, Blockchain, Web3, and emerging technologies.

Read More Articles