Java Collections From Fundamentals to Best Practices
Java Collections From Fundamentals to Best Practices
Fundamentals to Best
Practices
• Best Practices
AGENDA
• Demo
Introduction
What is a Collection?
• Dynamic Size
CODE DEMO
Reduced Programming Effort:
• The framework provides pre-built, well-tested, and
efficient data structures (Lists, Sets, Maps, etc.).
• You don't need to "reinvent the wheel" by
implementing these structures yourself.
• Focus on your application logic instead of low-level
data management. Benefits of Using
the Java
Collections
Framework
Increased Performance:
• Collections are implemented with performance in
mind, often using optimized algorithms.
• Choosing the right collection for the task can
significantly impact your application's speed and
efficiency (e.g., fast lookups in a HashMap).
Benefits of Using
the Java
Collections
Framework
Improved Code Reusability and Maintainability:
The framework provides a consistent and well-defined
API (interfaces like List, Set, Map).
Code becomes more readable and understandable as
you work with familiar collection types and methods.
Benefits of Using
the Java
Collections
Framework
Enhanced Flexibility and Adaptability:
• A wide variety of collection implementations are
available, each suited for different needs (e.g.,
ordered lists, unique elements, key-value pairs).
• Easily switch between different collection types if your
application's requirements change, without significant Benefits of Using
code rewrites (due to the common interfaces). the Java
Collections
Framework
Interoperability:
• Collections work seamlessly with other parts of the
Java ecosystem.
• Standardized way to handle groups of objects,
making it easier to exchange data between different
components of your application or with external
libraries. Benefits of Using
the Java
Collections
Framework
Interoperability:
• Collections work seamlessly with other parts of the
Java ecosystem.
• Standardized way to handle groups of objects,
making it easier to exchange data between different
components of your application or with external
libraries. Core Interfaces
and Classes of
the Collections
Framework
Collection:
Key Characteristic:
get(int index):
Modifying Elements:
size():
• Returns the number of elements in this list.
isEmpty():
• Returns true if this list contains no elements.
iterator():
listIterator():
• Returns a list iterator over the elements in this list (allows List: Commonly
bidirectional traversal and modification). Used Methods
listIterator(int index):
• get(index): O(1)
• set(index, element): O(1)
• add(element) (appending to the end):O(1)
• add(index, element) (inserting at a specific index):
O(n)
• remove(index): O(n)
Implementing List: • remove(Object element): O(n)
ArrayList
• contains(Object element): O(n)
• size(): O(1)
Use Cases - When to Use ArrayList
No Contiguous Memory:
• Elements in a LinkedList are not stored in contiguous
Implementing List: memory locations.
LinkedList • The order is maintained by the pointers between the
nodes.
No Initial Capacity:
• LinkedList does not have a fixed initial capacity like
ArrayList.
• It grows dynamically as elements are added.
Performance Characteristics (Big O Notation)
• get(index): O(n)
• set(index, element): O(n)
• add(element) (appending to the end): O(1)
• add(index, element) (inserting at a specific index):
O(n)
• remove(index): O(n)
• remove(Object element): O(n)
• contains(Object element): O(n)
• size(): O(1)
Implementing List:
LinkedList • addFirst(element), addLast(element),
offerFirst(element), offerLast(element): O(1)
Implementing List: Operations at the Head and Tail: Adding and removing
LinkedList elements from the beginning or end of a LinkedList are
very fast (O(1)).
Vector (Legacy):
• Similar to ArrayList but is synchronized (thread-safe).
• Generally less performant than ArrayList in single-
threaded environments.
• Largely superseded by ArrayList
Stack (Legacy):
• Extends Vector and implements a LIFO (Last-In, First-
Legacy Classes Out) stack.
• Provides methods like push(), pop(), and peek().
• Consider using ArrayDeque for better performance in
modern applications.
Working with Sets (HashSet, TreeSet,
LinkedHashSet)
Set:
• Models the mathematical concept of a set.
• Operations include adding, removing, and checking
for the presence of elements.
Key Characteristic:
• No Duplicate Elements: Each element in a Set must be
unique. Adding a duplicate element has no effect (it's Core Interfaces
typically ignored). of the
• Unordered (Generally): The order in which elements Collections
are stored and retrieved is not necessarily predictable Framework
or consistent(unless a specific implementation like
LinkedHashSet is used).
• Null Element (Implementation Dependent): Some Set
implementations (like HashSet and LinkedHashSet)
allow one null element, while others (like TreeSet) do
not.
Adding Elements:
add(E element):
• Adds the specified element to this set if it is not
already present.
• Returns true if the set was modified (i.e., the element
was added), and false otherwise.
Set:
Commonly Used
addAll(Collection<? extends E> c):
Methods
• Adds all of the elements in the specified collection to
this set if they are not already present.
• Returns true if this set changed as a result of the call.
Removing Elements:
remove(Object o):
• Removes the specified element from this set if it is
present.
• Returns true if the set contained the element (or
equivalently, if the set was modified as a result of the
call). Set:
removeAll(Collection<?> c): Commonly Used
• Removes from this set all of its elements that are
Methods
contained in the specified collection.
• Returns true if this set changed as a result of the call.
removeIf(Predicate<? super E> filter):
• Removes all elements of this collection that satisfy the
given predicate.
Checking for Elements:
contains(Object o):
• Returns true if this set contains the specified element.
containsAll(Collection<?> c):
• Returns true if this set contains all of the elements of the
specified collection.
Set:
Commonly Used
Getting Information: Methods
size():
• Returns the number of elements in this set (its cardinality).
isEmpty():
• Returns true if this set contains no elements.
Iterating Over the Set:
iterator():
CODE DEMO
Set Operations (Implemented through methods, but
conceptually important):
Sorted Order:
Elements are always maintained in a sorted order.
Implementing Set: • Natural Ordering: If the elements implement the
TreeSet Comparable interface, they are sorted according
to their compareTo() method.
first():
• Returns the first (lowest) element currently in this set.
last():
Implementing Set: • Returns the last (highest) element currently in this set.
TreeSet
headSet(E toElement):
• Returns a view of the portion of this set whose elements
are strictly less than toElement.
• The returned set is backed by this set, so changes in the
returned set are reflected in this set, and vice-versa.
Key Methods Specific to Sorted Sets (from the SortedSet
Interface, implemented by TreeSet):
tailSet(E fromElement):
• Returns a view of the portion of this set whose elements
are greater than or equal to fromElement.
• The returned set is backed by this set, so changes in the
Implementing Set: returned set are reflected in this set, and vice-versa.
TreeSet
Key Methods Specific to Sorted Sets (from the SortedSet
Interface, implemented by TreeSet):
CODE DEMO
Use Cases - When to Use TreeSet:
• Maintaining Sorted Elements: When you need a
collection that automatically keeps its elements sorted.
• Efficient Retrieval of Sorted Data: When you need to
iterate through the elements in a sorted manner.
• Implementing Sorted Sets: When you need the
properties of a Set (uniqueness) along with sorted
Implementing Set: order.
TreeSet • Range Queries: The sorted nature of TreeSet makes it
efficient for operations like finding elements within a
certain range
Underlying Data Structure:
• Internally uses a HashMap for storing elements (for
efficient uniqueness checks) and a doubly-linked list to
maintain the insertion order of elements.
Uniqueness:
• Like HashSet, LinkedHashSet ensures that all elements
are unique.
• It uses the hashCode() and equals() methods of the
elements to determine uniqueness.
Core Interfaces
Note: Map is not a subtype of the Collection interface. It of the
represents a fundamentally different way of organizing Collections
data. Framework
Key Characteristic:
• Stores key-value pairs
• Unique keys
• Values Can Be Duplicates
• No Guaranteed Order (unless a specific implementation
like LinkedHashMap or TreeMap is used)
Adding Entries:
get(Object key):
remove(Object key):
• Removes the mapping for the specified key from this
map if it is present.
• Returns the value that was previously associated with
the key, or null if the map contained no mapping for
the key. Map Interface:
Common
remove(Object key, Object value): Methods
• Removes the entry for the specified key only if it is
currently mapped to the specified value.
• Returns true if removed, false otherwise.
clear():
• Removes all of the mappings from this map.
Checking for Keys or Values:
containsKey(Object key):
• Returns true if this map contains a mapping for the
specified key.
containsValue(Object value):
• Returns true if this map maps one or more keys to the
specified value. Map Interface:
Common
Methods
Getting Information:
size():
• Returns the number of key-value mappings in this
map.
isEmpty():
• Returns true if this map contains no key-value
mappings.
Getting Views of the Map's Contents:
keySet():
• Returns a Set view of the keys contained in this map.
• The set is backed by the map, so changes to the map
are reflected in the set, and vice-versa
values():
Map Interface:
Common
• Returns a Collection view of the values contained in Methods
this map.
• The collection is backed by the map, so changes to
the map are reflected in the collection, and vice-
versa.
Getting Views of the Map's Contents:
entrySet():
• Returns a Set view of the mappings contained in this
map. Each element in the set is a Map.
• Entry object, which represents a key-value pair.
• The set is backed by the map, so changes to the map
are reflected in the set, and vice-versa. Map Interface:
The order of the set is implementation-dependent. Common
Methods
Iterating Over the Map:
CODE DEMO
Underlying Data Structure:
Hashing Mechanism:
• When you put a key-value pair into a HashMap, the
hashCode() method of the key is used to determine the
Implementing Map: bucket where the entry should be stored.
HashMap • If multiple keys have the same hashCode() (a collision), they
are placed in the same bucket (typically in a linked list).
• When you get a value based on a key, the hashCode() of
the key is again used to find the correct bucket, and then
the equals() method is used to find the specific key-value
pair within that bucket.
Uniqueness of Keys:
• HashMap ensures that all keys are unique.
• If you try to put a key that already exists, the old value
associated with that key is overwritten.
Sorted Keys:
• Entries are always maintained in a sorted order based
on their keys.
Natural Ordering:
• If the keys implement the Comparable interface, they
are sorted according to their compareTo() method.
Implementing Map:
TreeMap Uniqueness of Keys:
• Like all Map implementations, TreeMap enforces
unique keys.
• If you try to put a key that already exists, the old value
is overwritten.
firstKey():
• Returns the first (lowest) key currently in this map.
lastKey():
• Returns the last (highest) key currently in this map.
Implementing Map:
TreeMap headMap(K toKey):
• Returns a view of the portion of this map whose keys
are strictly less than toKey.
• The returned map is backed by this map, so changes
in the returned map are reflected in this map, and
vice-versa.
Key Methods Specific to Sorted Maps (from the
SortedMap Interface, implemented by TreeMap):
tailMap(K fromKey):
• Returns a view of the portion of this map whose keys
are greater than or equal to fromKey.
• The returned map is backed by this map, so changes
in the returned map are reflected in this map, and
Uniqueness of Keys: