Difference Between List and Set in Java
List and Set are both sub-interfaces of Collection, but they model different ideas:
- A
Listis an ordered sequence that allows duplicates and gives access by index, like a numbered to-do list. - A
Setis a collection of unique elements with no index, like a set of tags or a guest list where each name appears once.
1. Comparison Table
| Aspect | List | Set |
|---|---|---|
| Duplicates | Allowed | Not allowed (add returns false) |
| Order | Insertion order (positional) | Depends on implementation: none, insertion or sorted |
| Index access | get(i), set(i, x), add(i, x), indexOf | None |
| Null | Any number of nulls | HashSet/LinkedHashSet: one null; TreeSet: none |
| Main implementations | ArrayList, LinkedList, CopyOnWriteArrayList | HashSet, LinkedHashSet, TreeSet, EnumSet |
contains() | O(n) for ArrayList | O(1) for HashSet, O(log n) for TreeSet |
| Iterator | Iterator and bidirectional ListIterator | Iterator only |
| Equality | Same elements in the same order | Same elements, order ignored |
| Relies on | equals() | equals() + hashCode(), or compareTo() for TreeSet |
2. Same Data, Different Results
import java.util.*;
public class ListVsSet {
public static void main(String[] args) {
String[] tags = {"java", "spring", "java", "kafka", "spring", "docker"};
List<String> list = new ArrayList<>(Arrays.asList(tags));
Set<String> hash = new HashSet<>(Arrays.asList(tags));
Set<String> linked = new LinkedHashSet<>(Arrays.asList(tags));
Set<String> tree = new TreeSet<>(Arrays.asList(tags));
System.out.println("List : " + list + " (duplicates kept, insertion order)");
System.out.println("HashSet : " + hash + " (no duplicates, no guaranteed order)");
System.out.println("LinkedHashSet : " + linked + " (insertion order)");
System.out.println("TreeSet : " + tree + " (sorted)");
System.out.println("list.get(2) = " + list.get(2) + " (index access)");
System.out.println("list.indexOf(\"kafka\") = " + list.indexOf("kafka"));
System.out.println("set.add(\"java\") again returns " + hash.add("java"));
}
}
List : [java, spring, java, kafka, spring, docker] (duplicates kept, insertion order)
HashSet : [spring, java, kafka, docker] (no duplicates, no guaranteed order)
LinkedHashSet : [java, spring, kafka, docker] (insertion order)
TreeSet : [docker, java, kafka, spring] (sorted)
list.get(2) = java (index access)
list.indexOf("kafka") = 3
set.add("java") again returns false
3. Removing Duplicates and Fast Lookups
import java.util.*;
public class Dedupe {
record Email(String address) { } // records implement equals/hashCode, so sets work
public static void main(String[] args) {
List<Integer> orderIds = List.of(105, 101, 105, 103, 101);
List<Integer> unique = new ArrayList<>(new LinkedHashSet<>(orderIds)); // remove duplicates, keep order
System.out.println("unique ids: " + unique);
Set<Email> subscribers = new HashSet<>();
subscribers.add(new Email("asha@example.com"));
subscribers.add(new Email("asha@example.com"));
System.out.println("subscribers: " + subscribers.size());
// contains(): O(1) average for HashSet vs O(n) for ArrayList
List<Integer> big = new ArrayList<>();
for (int i = 0; i < 200_000; i++) big.add(i);
Set<Integer> bigSet = new HashSet<>(big);
long t1 = System.nanoTime(); for (int i = 0; i < 2_000; i++) big.contains(199_999);
long t2 = System.nanoTime(); for (int i = 0; i < 2_000; i++) bigSet.contains(199_999);
long t3 = System.nanoTime();
System.out.println("HashSet.contains much faster than List.contains: " + ((t2 - t1) > 10 * (t3 - t2)));
}
}
unique ids: [105, 101, 103] subscribers: 1 HashSet.contains much faster than List.contains: true
- Passing a list through a
LinkedHashSetremoves duplicates while keeping the original order. - Sets rely on
equalsandhashCode; records generate both, so equal records count once. - Membership tests on a
HashSetare constant time, whileArrayList.containsscans the whole list.
4. When to Use Which
| Use a List when… | Use a Set when… |
|---|---|
| Order or position matters (playlist, steps, history) | Each element must be unique (user IDs, tags, permissions) |
| Duplicates are meaningful (order lines, log entries) | You frequently check "is X present?" |
| You need index access or sorting in place | You need set operations: union, intersection, difference |
5. Summary
List: ordered, duplicates allowed, index access.Set: unique elements, no index, ordering depends on the implementation.- Sets give fast
containsand need correctequals/hashCode. - Convert a list to a
LinkedHashSetto remove duplicates while preserving order.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is the main difference between List and Set?
A List allows duplicates and keeps elements in positional order; a Set stores only unique elements and has no index.
Q2. Does a Set maintain insertion order?
HashSet does not, LinkedHashSet does, and TreeSet keeps elements sorted.
Q3. Can a Set contain null?
HashSet and LinkedHashSet allow one null; TreeSet does not (with natural ordering).
Q4. Can I access a Set element by index?
No. Iterate over it, or copy it into a list if you need positions.
Q5. How does a Set detect duplicates?
Hash-based sets use hashCode() and equals(); TreeSet uses compareTo() or a comparator.
Q6. What happens when I add a duplicate to a Set?
The set is unchanged and add() returns false.
Q7. How do I remove duplicates from a List?
new ArrayList<>(new LinkedHashSet<>(list)) or list.stream().distinct().toList().
Q8. Which is faster for contains()?
HashSet (O(1) on average) over ArrayList (O(n)).
Q9. Are List and Set interfaces or classes?
Interfaces. Use implementations such as ArrayList and HashSet.
Q10. Can I sort a Set?
Use a TreeSet, or copy the set into a list and sort the list.
Q11. How are two Lists or Sets compared with equals()?
Lists are equal if they have the same elements in the same order; sets are equal if they contain the same elements regardless of order.
Q12. What is ListIterator?
A List-only iterator that moves both forwards and backwards and can add or replace elements during iteration.
Q13. What happens if I modify an object stored in a HashSet?
If fields used in hashCode change, the set may no longer find it. Keep set elements immutable.
Q14. Is Map a List or a Set?
Neither. Map is a separate interface, but its keySet() is a Set and values() is a Collection.
Q15. How do I create immutable Lists and Sets?
List.of(...) and Set.of(...) (Java 9). Set.of throws if given duplicates.
Q16. Which uses more memory?
A HashSet generally uses more than an ArrayList, because it is backed by a HashMap with entry objects.
Q17. Can a List be converted to a Set and back?
Yes: new HashSet<>(list) and new ArrayList<>(set). Duplicates are lost when converting to a set.
Q18. What are set operations in Java?
addAll (union), retainAll (intersection) and removeAll (difference).
Q19. Are List and Set thread-safe?
The common implementations are not. Use concurrent versions such as CopyOnWriteArrayList or ConcurrentHashMap.newKeySet().
Q20. Which should I return from an API?
Return Set when uniqueness is part of the contract, and List when order or duplicates matter.