1. Overview
List, Set and Map in java are the most used interfaces of the collection framework. Collection framework has several interfaces and classes which are widely used in most java application. For storing data in collections, List, Set and Map are most often used interfaces. A difference between these interfaces is one of the questions asked at typical Java Developer interview on collection framework. In this article, we will discuss these three core Collection interfaces and the basic contract of each. We will be considering the concrete implementations for each of the interface. Performance characteristics of the implementations in space and time will also be listed.
2. Differences Based on Properties of an Interface
All collection interfaces have different underlying data structures. That is the primary reason for their behavior and properties. Collection interfaces can be easily differentiated and identified from their characteristics. Here are some key measurable characteristics for collection interfaces:
- Duplicate Objects
- Null Objects
- Preserve order of elements
- Cursors used to iterate over data
- Underlying data structure
Now, we will compare List, Set and Map on these characteristics. Knowing these differences will help us in identifying the correct collection to be used in a specific situation.
2.1 Duplicate Objects
List and Set are identical interfaces which stores objects, while Map stores key-value pairs. One primary difference between List and Set is, List allows duplicate objects while Set contract says that “No duplicate objects allowed”. While in a case of Map, it can have duplicate values but Keys should be unique.
So, it’s a straightforward statement, if we want unique values to be stored in a collection then use Set interface and if we want to store key-value pairs then consider Map interface.
equals() method is being used to detect duplication of an object.
Please note that SortedSet uses compareTo() method for the same purpose.
2.2 Null Objects
Another significant difference between them is allowing null
objects. Lists allow null
objects and we can have multiple null
elements because it allows duplicates too. Generally Set allows one null
element as value must be unique in a set, but depending on implementation, Set may not accpet null
value. Maps allow one null
key and multiple null
values.
2.3 Preserve Order of Elements
If we want to access elements by an index then we should consider List over other collection interfaces. List maintains an order of elements so we can retrieve any element through its index.
Set interface doesn’t enforce ordering of elements which means a Set implementation can be unordered collection. Some of the Set implementation classes like LinkedHashSet, SortedSet, SortedMap maintains order.
Map is an unordered collection too. Set and Map do not preserve insertion order while List does.
We can use get() method with List but we cannot use it with Set and Map due to nature of an unordered collection.
2.4 Examples
Consider an example, where we have a Student
object:
Student firstStudent = new Student(1,"A");
Let’s use Student
object with these three interfaces:
List:
List<Student> studentsList = new ArrayList<>(); Student firstStudent = new Student(1,"A"); studentsList.add(firstStudent); // example of null object insertion studentsSet.add(null); studentsSet.add(firstStudent); // duplicate object insertion studentsSet.add(null);
Set:
Set<Student> studentsSet= new HashSet<>(); studentsSet.add(firstStudent); // example of null object insertion studentsSet.add(null); studentsSet.add(firstStudent); // duplicate value insertion studentsSet.add(null);
Map:
Map<Integer, String> studentMap = new HashMap<>(); studentMap.put(firstStudent.getSid(), firstStudent.getSname()); studentMap.put(1, "B");
We used ArrayList, HashSet and HashMap implementation of List, Set and Map interface respectively. We inserted duplicate and null
values too.
When we enter duplicate values in Set or duplicate keys in Map, it won’t throw any compilation error. It will store only one object from all the duplicates. This can be useful when you wanted to store only unique objects in a collections.
2.5 Cursor Used to Iterate Over Data
For List, we have special ListIterator, which can be used to perform iteration over a list and allow us to execute various functions on elements. ListIterator is rich providing methods for additional operations. We can also use regular Iterator with a list
While for Set, it just returns Iterator object, we don’t have any special iterator for it.
A Map is a collection of key-value pairs so we have multiple ways to access map. We can access it by keys, by values and through entry set as well.
Now, let’s iterate over above example and compare results in each case:
List:
ListIterator listIterator = studentsList.listIterator(); System.out.println("List"); while (listIterator.hasNext()){ System.out.println(listIterator.next()); }
Output:
List [email protected] null [email protected] null
We can also use get() method to retrieve an element from specific index in a list:
System.out.println("Using get index " + studentsList.get(2));
Set:
Iterator iterator = studentsSet.iterator(); System.out.println("Set"); while(iterator.hasNext()){ System.out.println(iterator.next()); }
Output:
Set null [email protected]
Map:
System.out.println("Iterate using Entry Set"); for(Map.Entry entry : studentMap.entrySet()){ System.out.println(entry.getKey() + ":" + entry.getValue()); } System.out.println("Iterate using Key Set"); for(int key : studentMap.keySet()){ System.out.println(key + ":" + studentMap.get(key)); }
Output:
Iterate using Entry Set 1:B Iterate using Key Set 1:B
From an output of Set and Map, we can see that both allow only unique values and keys respectively. While with a List, duplicate objects are being treated as separate elements.
2.6 Underlying Data Structures
Lists are based on variable size array and it uses a similar approach for indexing elements.
Set uses internal implementation of Map and it is not index based structure.
A Map uses various hashing techniques to store key-value pairs.
Due to different underlying data structures, their behavior and purpose are quite different from each other.
2.7 Other Differences
List and Set both have Collection as a parent interface, while Map is not extending Collection interface.
Implementation classes for each of them are as below:
List – ArrayList, Vector, LinkedList
Set – HashSet, LinkedHashSet, TreeSet
Map – HashTable, LinkedHashMap, HashMap, TreeMap
2.8 List vs Set vs Map
Let’s summarize all differences we discussed:
All Implementation classes of these interfaces follow the similar contract with their parent interface. All of them have both synchronized and unsynchronized implementations.
3. Performance Comparisons for Implementations of List, Set and Map
As we have already looked at the various differences of List, Set and Map implementations. Let’s now have a look at the performance of the various implementations of these interfaces. We will be looking at methods that are most widely used.
List:
Implementation | add() | remove() | get() | contains() | Data Structure |
---|---|---|---|---|---|
ArrayList | O(1) | O(n) | O(1) | O(n) | Resizable Array |
LinkedList | O(1) | O(1) | O(n) | O(n) | Linked List |
CopyOnWriteArrayList | O(n) | O(n) | O(1) | O(n) | Resizable Array |
Set:
Implementation | add() | remove() | contains() | next() | size() | Data Structure |
HashSet | O(1) | O(1) | O(1) | O(h/n) | O(1) | Hash Table |
LinkedHashSet | O(1) | O(1) | O(1) | O(1) | O(1) | Hash Table + Linked List |
EnumSet | O(1) | O(1) | O(1) | O(1) | O(1) | Bit Vector |
TreeSet | O(logn) | O(logn) | O(logn) | O(logn) | O(1) | Balanced Tree |
CopyOnWriteArraySet | O(n) | O(n) | O(n) | O(1) | O(1) | Resizable Array |
ConcurrentSkipListSet | O(logn) | O(logn) | O(logn) | O(1) | O(n) | Skip List |
Map:
Implementation | get() | containsKey() | next() | Data Structure |
---|---|---|---|---|
HashMap | O(1) | O(1) | O(h/n) | Hash Table |
LinkedHashMap | O(1) | O(1) | O(1) | Hash Table + Linked List |
IdentityHashMap | O(1) | O(1) | O(h/n) | Resizable Array |
WeakHashMap | O(1) | O(1) | O(h/n) | Hash Table |
EnumMap | O(1) | O(1) | O(1) | Resizable Array |
TreeMap | O(log n) | O(log n) | O(log n) | Balanced Tree |
ConcurrentHashMap | O(1) | O(1) | O(h/n) | Hash Table |
ConcurrentSkipListMap | O(log n) | O(log n) | O(1) | Skip List |
Please note that “h” represents table capacity.
4. Summary
After looking at the differences between List, Set and Map, we have a good idea of the characteristics of these interfaces. These collections serve different purposes. It is important to know the differences as this helps in deciding for a particular collection for a specific problem faced.
You may also like