Exploring Collections in Java: Key Differences and Best Practices
I am a backend developer, interested in writing about backend engineering, DevOps and tooling.
Introduction
Collections are a cornerstone of Java programming, providing a framework for storing and manipulating groups of objects. The Java Collections Framework (JCF) offers a variety of interfaces and classes designed to meet different needs, from simple lists and sets to more complex maps. Understanding the differences between these collections is crucial for writing efficient and maintainable code. In this article, we’ll explore the main types of collections in Java, highlighting their key differences, use cases, and providing code examples to illustrate each collection.
Types of Collections
The Java Collections Framework is built around several key interfaces, each of which has multiple implementations suited for different use cases. The most commonly used collections are List, Set, and Map. Let’s take a closer look at each of these.
List
A List is an ordered collection that allows duplicate elements. It provides control over the position of inserted elements and allows access to elements by their index.
Common Implementations:
ArrayList: A resizable array that provides fast random access to elements. It’s best used when you need fast iteration and don’t frequently insert or remove elements in the middle of the list.LinkedList: A doubly-linked list that is more efficient thanArrayListfor inserting or deleting elements in the middle of the list. However, it offers slower access by index.
Key Differences:
Performance:
ArrayListhas O(1) time complexity for access by index, whileLinkedListhas O(n).Memory:
ArrayListconsumes less memory thanLinkedListwhen storing a large number of elements.Use Case: Use
ArrayListwhen frequent random access is needed, andLinkedListwhen frequent insertions and deletions in the list are required.
Code Example:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListExample {
public static void main(String[] args) {
// Using ArrayList
List<String> arrayList = new ArrayList<>();
arrayList.add("Alice");
arrayList.add("Bob");
arrayList.add("Charlie");
System.out.println("ArrayList: " + arrayList);
// Using LinkedList
List<String> linkedList = new LinkedList<>();
linkedList.add("Alice");
linkedList.add("Bob");
linkedList.add("Charlie");
linkedList.add(1, "David");
System.out.println("LinkedList: " + linkedList);
}
}
Set
A Set is an unordered collection that does not allow duplicate elements. It’s ideal for scenarios where you want to ensure that no duplicate elements exist in your collection.
Common Implementations:
HashSet: Implements theSetinterface, backed by a hash table. It offers constant time performance for basic operations like add, remove, and contains.TreeSet: Implements theSetinterface, using a tree structure to store elements. It maintains elements in a sorted order and offers log(n) time complexity for basic operations.LinkedHashSet: A hybrid betweenHashSetandLinkedHashMap, it maintains a doubly-linked list running through all its entries, preserving the insertion order.
Key Differences:
Ordering:
HashSetdoes not guarantee any order, whileTreeSetsorts elements based on their natural ordering or a provided comparator.LinkedHashSetmaintains the order in which elements were inserted.Performance:
HashSetgenerally offers faster performance thanTreeSet, butTreeSetis preferable when you need a sorted set.Use Case: Use
HashSetfor fast lookup andTreeSetwhen you need elements in a specific order.
Code Example:
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class SetExample {
public static void main(String[] args) {
// Using HashSet
Set<String> hashSet = new HashSet<>();
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Cherry");
hashSet.add("Banana"); // Duplicate, won't be added
System.out.println("HashSet: " + hashSet);
// Using TreeSet
Set<String> treeSet = new TreeSet<>();
treeSet.add("Apple");
treeSet.add("Banana");
treeSet.add("Cherry");
System.out.println("TreeSet (Sorted): " + treeSet);
// Using LinkedHashSet
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Apple");
linkedHashSet.add("Banana");
linkedHashSet.add("Cherry");
System.out.println("LinkedHashSet (Insertion Order): " + linkedHashSet);
}
}
Map
A Map is a collection that maps keys to values. It does not allow duplicate keys but can have duplicate values.
Common Implementations:
HashMap: A hash table-based implementation of theMapinterface. It provides constant-time performance for get and put operations.TreeMap: AMapthat maintains its keys in sorted order, implemented using a red-black tree.LinkedHashMap: ExtendsHashMapto maintain the order of elements based on their insertion or access order.
Key Differences:
Ordering:
HashMapdoes not guarantee any order of keys, whileTreeMapmaintains keys in a sorted order.LinkedHashMappreserves the insertion order.Performance:
HashMapis faster thanTreeMapfor most operations. However,TreeMapis useful when you need a map with sorted keys.Use Case: Use
HashMapfor quick lookups,TreeMapwhen you need sorted keys, andLinkedHashMapwhen the order of iteration is important.
Code Example:
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
public class MapExample {
public static void main(String[] args) {
// Using HashMap
Map<Integer, String> hashMap = new HashMap<>();
hashMap.put(1, "One");
hashMap.put(2, "Two");
hashMap.put(3, "Three");
System.out.println("HashMap: " + hashMap);
// Using TreeMap
Map<Integer, String> treeMap = new TreeMap<>();
treeMap.put(1, "One");
treeMap.put(2, "Two");
treeMap.put(3, "Three");
System.out.println("TreeMap (Sorted): " + treeMap);
// Using LinkedHashMap
Map<Integer, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put(1, "One");
linkedHashMap.put(2, "Two");
linkedHashMap.put(3, "Three");
System.out.println("LinkedHashMap (Insertion Order): " + linkedHashMap);
}
}
Conclusion
Understanding the differences between various collections in Java is essential for choosing the right tool for the job. Whether you need to maintain order, ensure uniqueness, or optimize for performance, the Java Collections Framework provides a wealth of options. By selecting the appropriate collection type and understanding their performance characteristics, you can improve the efficiency and clarity of your code, making your applications more robust and maintainable.




