Keywords:
Introduction
In Java programming, understanding the distinctions between Set and List is essential for making the right data structure choice for your application. Both are fundamental components of the Java Collections Framework, but they serve different purposes. In this article, we will explore the key differences between Set vs List in Java and how to choose between them based on your requirements.
Key Differences between Set and List in Java
- Order of Elements
- Handling Duplicate Elements
- Access by Index
- Performance Comparison
- Null Elements Handling
- Java Set Implementations vs List Implementations
Getting Started
1. Order of Elements
- Set: Does not guarantee the order of elements (except for specific implementations like LinkedHashSet which maintains insertion order, or TreeSet which maintains elements in sorted order).
- List: Maintains the insertion order of elements. The order in which you add elements is the order in which they are retrieved.
2. Handling Duplicate Elements
- Set: Does not allow duplicate elements. Every element in a
Set
must be unique. - List: Allows duplicate elements. You can have multiple occurrences of the same element in a List.
3. Access by Index
- Set: Does not provide access by index. There are no methods to get an element by its position.
- List: Provides access by index. You can retrieve, modify, or remove elements using their position (Eg: list.get(index)).
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class Main{
public static void main(String[] args) {
List<String> list = Arrays.asList("cat", "bag", "apple");
System.out.println(list.get(0)); // Gives output as "cat"
Set<String> set = new HashSet<>();
set.add("cat");
set.add("bag");
set.add("apple");
System.out.println(set.get(0)); // Compile Error: cannot find symbol
}
}
Output:
cat
java: cannot find symbol
symbol: method get(int)
location: variable set of type java.util.Set<java.lang.String>
4. Performance Comparison
Set: Generally offers better performance for operations like searching and adding when compared to a List, especially with implementations like HashSet (O(1) for basic operations). List: May have slower search times (O(n)) for unsorted lists, but indexing operations are O(1) for implementations like ArrayList.
import java.util.*;
class Main{
public static void main(String[] args) {
// Set (HashSet)
Set<Integer> hashSet = new HashSet<>();
for (int i = 1; i <= 1000000; i++) {
hashSet.add(i);
}
long startTime = System.nanoTime();
boolean setContains = hashSet.contains(500000); // O(1) search
long endTime = System.nanoTime();
System.out.println("HashSet search time: " + (endTime - startTime) + " ns");
// List (ArrayList)
List<Integer> arrayList = new ArrayList<>();
for (int i = 1; i <= 1000000; i++) {
arrayList.add(i);
}
startTime = System.nanoTime();
boolean listContains = arrayList.contains(500000); // O(n) search
endTime = System.nanoTime();
System.out.println("ArrayList search time: " + (endTime - startTime) + " ns");
}
}
Output:
HashSet search time: 67400 ns
ArrayList search time: 20147900 ns
Process finished with exit code 0
5. Null Elements Handling
Set:
1. HashSet: Allows only a single null element.
import java.util.*;
class Main{
public static void main(String[] args) {
// Set (HashSet)
Set<Integer> hashSet = new HashSet<>();
for (int i = 1; i <= 1000000; i++) {
hashSet.add(i);
}
long startTime = System.nanoTime();
boolean setContains = hashSet.contains(500000); // O(1) search
long endTime = System.nanoTime();
System.out.println("HashSet search time: " + (endTime - startTime) + " ns");
// List (ArrayList)
List<Integer> arrayList = new ArrayList<>();
for (int i = 1; i <= 1000000; i++) {
arrayList.add(i);
}
startTime = System.nanoTime();
boolean listContains = arrayList.contains(500000); // O(n) search
endTime = System.nanoTime();
System.out.println("ArrayList search time: " + (endTime - startTime) + " ns");
}
}
Output:
HashSet search time: 67400 ns
ArrayList search time: 20147900 ns
Process finished with exit code 0
5. Null Elements Handling
1. HashSet: Allows only a single null element.
import java.util.HashSet;
import java.util.Set;
class Main{
public static void main(String[] args) {
Set<String> hashSet = new HashSet<>();
hashSet.add(null);
hashSet.add(null); // Duplicate null
System.out.println(hashSet); // Ignore duplicates
}
}
Output:
[null]
Process finished with exit code 0
2. LinkedHashSet: also allows only a single null element.
import java.util.LinkedHashSet;
import java.util.Set;
class Main{
public static void main(String[] args) {
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add(null);
linkedHashSet.add(null); // Duplicate null
System.out.println(linkedHashSet); // Ignore duplicates
}
}
Output:
[null]
Process finished with exit code 0
3. TreeSet: Doesn't allow null because it relies on sorting/comparison.
import java.util.TreeSet;
import java.util.Set;
class Main{
public static void main(String[] args) {
// TreeSet doesn't allow null
try {
Set<String> treeSet = new TreeSet<>();
treeSet.add(null);
} catch (NullPointerException e) {
System.out.println("TreeSet doesn't allow null: " + e.getMessage());
}
}
}
Output:
TreeSet doesn't allow null: null
Process finished with exit code 0
List: Allows multiple null elements in implementations like ArrayList and LinkedList.
import java.util.ArrayList;
import java.util.List;
class Main{
public static void main(String[] args) {
// ArrayList allows multiple null elements
List<String> arrayList = new ArrayList<>();
arrayList.add(null);
arrayList.add(null);
System.out.println("ArrayList: " + arrayList); // Allows multiple null elements
}
}
Output:
ArrayList: [null, null]
Process finished with exit code 0
6. Java Set Implementation vs List Implementation
Set:HashSet
: Unordered, does not maintain insertion order.LinkedHashSet
: Maintains insertion order.TreeSet
: Maintains elements in sorted order (requires Comparable
or a Comparator
).
List: ArrayList
: Resizable array, faster for random access.LinkedList
: Doubly-linked list, faster for insertions and deletions.
import java.util.*;
class Main{
public static void main(String[] args) {
// HashSet: Unordered
Set<Integer> hashSet = new HashSet<>();
hashSet.add(42);
hashSet.add(3);
hashSet.add(15);
hashSet.add(8);
hashSet.add(23);
System.out.println("HashSet (Unordered): " + hashSet);
// LinkedHashSet: Maintains insertion order
Set<Integer> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add(42);
linkedHashSet.add(3);
linkedHashSet.add(15);
linkedHashSet.add(8);
linkedHashSet.add(23);
System.out.println("LinkedHashSet (Insertion Order): " + linkedHashSet);
// TreeSet: Sorted order
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(42);
treeSet.add(3);
treeSet.add(15);
treeSet.add(8);
treeSet.add(23);
System.out.println("TreeSet (Sorted Order): " + treeSet);
// ArrayList: Resizable array, random access
List<Integer> arrayList = new ArrayList<>();
arrayList.add(42);
arrayList.add(3);
arrayList.add(15);
arrayList.add(8);
arrayList.add(23);
System.out.println("ArrayList: " + arrayList);
System.out.println("Random Access (Index 2): " + arrayList.get(2));
// LinkedList: Doubly-linked list
List<Integer> linkedList = new LinkedList<>();
linkedList.add(42);
linkedList.add(3);
linkedList.add(15);
linkedList.add(8);
linkedList.add(23);
System.out.println("LinkedList: " + linkedList);
((LinkedList<Integer>) linkedList).addFirst(0);
System.out.println("After adding at the beginning: " + linkedList);
}
}
Output:
HashSet (Unordered): [3, 23, 8, 42, 15]
LinkedHashSet (Insertion Order): [42, 3, 15, 8, 23]
TreeSet (Sorted Order): [3, 8, 15, 23, 42]
ArrayList: [42, 3, 15, 8, 23]
Random Access (Index 2): 15
LinkedList: [42, 3, 15, 8, 23]
After adding at the beginning: [0, 42, 3, 15, 8, 23]
Process finished with exit code 0
import java.util.ArrayList;
import java.util.List;
class Main{
public static void main(String[] args) {
// ArrayList allows multiple null elements
List<String> arrayList = new ArrayList<>();
arrayList.add(null);
arrayList.add(null);
System.out.println("ArrayList: " + arrayList); // Allows multiple null elements
}
}
Output:
ArrayList: [null, null]
Process finished with exit code 0
6. Java Set Implementation vs List Implementation
HashSet
: Unordered, does not maintain insertion order.LinkedHashSet
: Maintains insertion order.TreeSet
: Maintains elements in sorted order (requiresComparable
or aComparator
).
ArrayList
: Resizable array, faster for random access.LinkedList
: Doubly-linked list, faster for insertions and deletions.
import java.util.*;
class Main{
public static void main(String[] args) {
// HashSet: Unordered
Set<Integer> hashSet = new HashSet<>();
hashSet.add(42);
hashSet.add(3);
hashSet.add(15);
hashSet.add(8);
hashSet.add(23);
System.out.println("HashSet (Unordered): " + hashSet);
// LinkedHashSet: Maintains insertion order
Set<Integer> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add(42);
linkedHashSet.add(3);
linkedHashSet.add(15);
linkedHashSet.add(8);
linkedHashSet.add(23);
System.out.println("LinkedHashSet (Insertion Order): " + linkedHashSet);
// TreeSet: Sorted order
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(42);
treeSet.add(3);
treeSet.add(15);
treeSet.add(8);
treeSet.add(23);
System.out.println("TreeSet (Sorted Order): " + treeSet);
// ArrayList: Resizable array, random access
List<Integer> arrayList = new ArrayList<>();
arrayList.add(42);
arrayList.add(3);
arrayList.add(15);
arrayList.add(8);
arrayList.add(23);
System.out.println("ArrayList: " + arrayList);
System.out.println("Random Access (Index 2): " + arrayList.get(2));
// LinkedList: Doubly-linked list
List<Integer> linkedList = new LinkedList<>();
linkedList.add(42);
linkedList.add(3);
linkedList.add(15);
linkedList.add(8);
linkedList.add(23);
System.out.println("LinkedList: " + linkedList);
((LinkedList<Integer>) linkedList).addFirst(0);
System.out.println("After adding at the beginning: " + linkedList);
}
}
Output:
HashSet (Unordered): [3, 23, 8, 42, 15]
LinkedHashSet (Insertion Order): [42, 3, 15, 8, 23]
TreeSet (Sorted Order): [3, 8, 15, 23, 42]
ArrayList: [42, 3, 15, 8, 23]
Random Access (Index 2): 15
LinkedList: [42, 3, 15, 8, 23]
After adding at the beginning: [0, 42, 3, 15, 8, 23]
Process finished with exit code 0
0 Comments