Understanding the Different Data-structures
Arrays are fixed-size, contiguous memory blocks that store elements of the same data type.
Internal Structure: Elements are stored in adjacent memory locations, allowing for constant-time access using indices.
Usage Scenario: When you need a fixed-size collection with fast access by index.
Real-time Use Case: Storing a list of fixed-size data, like months of the year or days of the week.
int[] numbers = new int[5];
numbers[0] = 1;
ArrayList is a resizable array implementation of the List interface.
Internal Structure: Backed by a dynamic array that grows as needed.
Usage Scenario: When you need frequent read operations and infrequent insert/delete operations.
Real-time Use Case: Implementing a shopping cart in an e-commerce application. Ex: Amazon Cart
ArrayList<String> shoppingCart = new ArrayList<>();
shoppingCart.add("Laptop");
LinkedList is a doubly linked list implementation of the List interface.
Internal Structure: Each element (node) contains data and references to the previous and next nodes.
Usage Scenario: When you need frequent insert/delete operations, especially at the beginning or end of the list.
Real-time Use Case: Implementing an undo/redo functionality in a text editor. Ex: Playlist
LinkedList<String> actions = new LinkedList<>();
actions.addFirst("Type 'Hello'");
Stack is a Last-In-First-Out (LIFO) data structure.
Internal Structure: Typically implemented using an array or linked list.
Usage Scenario: When you need to process elements in reverse order of their addition.
Real-time Use Case: Implementing the back button functionality in a web browser.
Stack<String> browserHistory = new Stack<>();
browserHistory.push("https://www.example.com");
PriorityQueue is a queue where elements are ordered based on their natural order or a custom comparator.
Internal Structure: Typically implemented using a heap data structure.
Usage Scenario: When you need to process elements based on their priority.
Real-time Use Case: Implementing a task scheduler where tasks have different priorities. Ex: Emergency Patient
PriorityQueue<Integer> taskPriorities = new PriorityQueue<>();
taskPriorities.offer(5);
Vector is a thread-safe, dynamic array implementation like ArrayList.
Internal Structure: Backed by a resizable array, with synchronized methods for thread safety.
Usage Scenario: When you need a thread-safe, dynamically growing array.
Real-time Use Case: Implementing a shared resource list in a multi-threaded application.
Vector<String> sharedResources = new Vector<> ();
sharedResources.add("Database Connection");
Deque (double-ended queue) allows insertion and removal at both ends.
Internal Structure: Can be implemented using a doubly linked list or a circular array.
Usage Scenario: When you need to add or remove elements from both ends efficiently.
Real-time Use Case: Implementing a palindrome checker. Ex: Browser History
Deque<Character> palindrome = new ArrayDeque<>();
palindrome.addFirst('r');
palindrome.addLast('a');
HashSet is an unordered collection that does not allow duplicates.
Internal Structure: Backed by a hash table (HashMap).
Usage Scenario: When you need to store unique elements and don’t care about order.
Real-time Use Case: Implementing a unique visitor counter for a website.
Ex: Subscribers
HashSet<String> uniqueVisitors = new HashSet<>();
uniqueVisitors.add("user123");
LinkedHashSet is an ordered version of HashSet that maintains insertion order.
Internal Structure: Combines a hash table with a linked list to maintain order.
Usage Scenario: When you need to store unique elements and maintain insertion order.
Real-time Use Case: Implementing a cache with a “least recently used” eviction policy. Ex: Tracking user actions on a website
LinkedHashSet<String> cache = new LinkedHashSet<>();
cache.add("recentItem");
TreeSet is a sorted set implementation based on a tree structure.
Internal Structure: Typically implemented using a self-balancing binary search tree (Red-Black tree).
Usage Scenario: When you need to store unique elements in sorted order.
Real-time Use Case: Implementing a leaderboard in a game.
TreeSet<Integer> leaderboard = new TreeSet<>();
leaderboard.add(1000);
HashMap
Internal Structure:
HashMap uses an array of linked lists (or balanced trees in Java 8+) to store key-value pairs.
Usage Scenario:
Use HashMap when you need fast insertion, deletion, and lookup operations, and don’t require keys to be sorted.
Real-time Use Case:
Implementing a cache system where quick access to data based on unique identifiers is crucial, such as a user session store in a web application.
HashMap<KeyType, ValueType> mapName = new HashMap<>();
mapName.put(key, value);
TreeMap
Internal Structure: TreeMap is implemented as a Red-Black tree, a self-balancing binary search tree.
Usage Scenario: Use TreeMap when you need to maintain keys in a sorted order or require operations that depend on ordering, like finding the closest matches or ranges of keys.
Real-time Use Case: Implementing a leaderboard system in a game where scores (keys) need to be kept in sorted order, allowing for efficient retrieval of top scores or score ranges.
TreeMap<Integer, String> leaderboard = new TreeMap<>(Collections.reverseOrder());
leaderboard.put(100, "nani");