Project Scenario: E-commerce Warehouse Inventory System
Problem Statement: Design an inventory management system for an e-commerce warehouse that needs to:
Track products in real-time
Support fast lookups by product ID and category
Maintain products sorted by price for quick filtering
Manage inventory levels and alert when stock is low
Show product relationships (frequently bought together)
This project implements an Inventory Management System for an e-commerce warehouse using various Data Structures and Algorithms to efficiently manage products, track inventory, and provide real-time insights.
Key Features:
Product Management (Add, Update, Delete)
Real-time Inventory Tracking
Low Stock Alerts
Category-wise Product Filtering
Price-based Sorting & Searching
Product Relationship Management (Frequently Bought Together)
2. System Architecture
The system is built using the following Data Structures and Algorithms:
Component | Data Structure/Algorithm | Purpose |
---|---|---|
Product Lookup | HashMap (ConcurrentHashMap) | O(1) access by Product ID |
Price-based Sorting | TreeSet (Red-Black Tree) | Maintains sorted order by price |
Low Stock Alerts | PriorityQueue (Min-Heap) | Efficiently tracks low-stock items |
Category Index | HashMap<String, List<Product>> | Groups products by category |
Product Relationships | Graph (Adjacency List) | Tracks frequently bought together items |
Price Filtering | Binary Search | Efficient range queries |
Sorting | QuickSort | Alternative sorting method |
Solution Implementation
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
class Product implements Comparable<Product> {
String id;
String name;
String category;
double price;
int quantity;
List<String> relatedProducts;
public Product(String id, String name, String category, double price, int quantity) {
this.id = id;
this.name = name;
this.category = category;
this.price = price;
this.quantity = quantity;
this.relatedProducts = new ArrayList<>();
}
public void addRelatedProduct(String productId) {
relatedProducts.add(productId);
}
@Override
public int compareTo(Product other) {
return Double.compare(this.price, other.price);
}
@Override
public String toString() {
return String.format("%s - %s ($%.2f, Qty: %d)", id, name, price, quantity);
}
}
class InventoryManagementSystem {
// Hash Table for O(1) product lookup by ID
private Map<String, Product> productTable;
// Tree structure for products sorted by price
private TreeSet<Product> productsByPrice;
// Graph for product relationships
private Map<String, List<String>> productGraph;
// Heap for low stock alerts
private PriorityQueue<Product> lowStockAlert;
// Array for category index
private Map<String, List<Product>> categoryIndex;
public InventoryManagementSystem() {
productTable = new ConcurrentHashMap<>(); // Thread-safe for real-time updates
productsByPrice = new TreeSet<>();
productGraph = new HashMap<>();
lowStockAlert = new PriorityQueue<>(Comparator.comparingInt(p -> p.quantity));
categoryIndex = new HashMap<>();
}
// Add product to system (O(log n) for TreeSet)
public void addProduct(Product product) {
productTable.put(product.id, product);
productsByPrice.add(product);
// Maintain category index
categoryIndex.computeIfAbsent(product.category, k -> new ArrayList<>()).add(product);
// Add to low stock monitoring
checkLowStock(product);
// Initialize graph node
productGraph.putIfAbsent(product.id, new ArrayList<>());
}
// Binary search in sorted products by price (O(log n))
public List<Product> getProductsInPriceRange(double min, double max) {
Product dummyMin = new Product("", "", "", min, 0);
Product dummyMax = new Product("", "", "", max, 0);
return new ArrayList<>(productsByPrice.subSet(dummyMin, true, dummyMax, true));
}
// O(1) lookup by product ID
public Product getProductById(String id) {
return productTable.get(id);
}
// Get products by category (O(1) for access, O(n) for copy)
public List<Product> getProductsByCategory(String category) {
return new ArrayList<>(categoryIndex.getOrDefault(category, Collections.emptyList()));
}
// Add relationship between products (graph edge)
public void addProductRelationship(String productId1, String productId2) {
if (productTable.containsKey(productId1) && productTable.containsKey(productId2)) {
productGraph.get(productId1).add(productId2);
productGraph.get(productId2).add(productId1);
// Also add to the product objects
productTable.get(productId1).addRelatedProduct(productId2);
productTable.get(productId2).addRelatedProduct(productId1);
}
}
// Get frequently bought together products (graph neighbors)
public List<Product> getRelatedProducts(String productId) {
List<Product> related = new ArrayList<>();
for (String relatedId : productGraph.getOrDefault(productId, Collections.emptyList())) {
related.add(productTable.get(relatedId));
}
return related;
}
// Update inventory (O(n) for heap update)
public void updateInventory(String productId, int quantityChange) {
Product product = productTable.get(productId);
if (product != null) {
// Remove from TreeSet to maintain sorting
productsByPrice.remove(product);
// Update quantity
product.quantity += quantityChange;
// Add back to TreeSet
productsByPrice.add(product);
// Check stock level
checkLowStock(product);
}
}
private void checkLowStock(Product product) {
if (product.quantity < 5) { // Threshold for low stock
lowStockAlert.remove(product); // Remove if already present
lowStockAlert.add(product);
} else {
lowStockAlert.remove(product);
}
}
// Get low stock alerts (O(1) for peek)
public List<Product> getLowStockAlerts() {
List<Product> alerts = new ArrayList<>();
PriorityQueue<Product> temp = new PriorityQueue<>(lowStockAlert);
while (!temp.isEmpty()) {
alerts.add(temp.poll());
}
return alerts;
}
// Merge two categories (using Union-Find concept)
public void mergeCategories(String category1, String category2) {
List<Product> list1 = categoryIndex.get(category1);
List<Product> list2 = categoryIndex.get(category2);
if (list1 != null && list2 != null) {
list1.addAll(list2);
categoryIndex.put(category2, list1);
}
}
// Sort products by price using QuickSort (alternative to TreeSet)
public List<Product> getProductsSortedByPrice() {
List<Product> products = new ArrayList<>(productTable.values());
quickSort(products, 0, products.size() - 1);
return products;
}
private void quickSort(List<Product> products, int low, int high) {
if (low < high) {
int pi = partition(products, low, high);
quickSort(products, low, pi - 1);
quickSort(products, pi + 1, high);
}
}
private int partition(List<Product> products, int low, int high) {
Product pivot = products.get(high);
int i = low - 1;
for (int j = low; j < high; j++) {
if (products.get(j).compareTo(pivot) <= 0) {
i++;
Collections.swap(products, i, j);
}
}
Collections.swap(products, i + 1, high);
return i + 1;
}
// Binary search in sorted array (alternative to TreeSet)
public Product binarySearchByPrice(List<Product> sortedProducts, double targetPrice) {
int left = 0;
int right = sortedProducts.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
double midPrice = sortedProducts.get(mid).price;
if (midPrice == targetPrice) {
return sortedProducts.get(mid);
} else if (midPrice < targetPrice) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return null;
}
}
public class Main {
public static void main(String[] args) {
InventoryManagementSystem ims = new InventoryManagementSystem();
// Add products
ims.addProduct(new Product("P100", "Laptop", "Electronics", 999.99, 10));
ims.addProduct(new Product("P101", "Mouse", "Electronics", 19.99, 50));
ims.addProduct(new Product("P102", "Keyboard", "Electronics", 49.99, 30));
ims.addProduct(new Product("P103", "Monitor", "Electronics", 199.99, 15));
ims.addProduct(new Product("P104", "Desk", "Furniture", 149.99, 8));
ims.addProduct(new Product("P105", "Chair", "Furniture", 79.99, 12));
ims.addProduct(new Product("P106", "Mouse Pad", "Accessories", 9.99, 100));
// Add relationships
ims.addProductRelationship("P100", "P101"); // Laptop and Mouse
ims.addProductRelationship("P100", "P102"); // Laptop and Keyboard
ims.addProductRelationship("P100", "P103"); // Laptop and Monitor
ims.addProductRelationship("P101", "P106"); // Mouse and Mouse Pad
ims.addProductRelationship("P104", "P105"); // Desk and Chair
// Update inventory
ims.updateInventory("P100", -8); // Sell 8 laptops
ims.updateInventory("P104", -5); // Sell 5 desks
// Demonstrate features
System.out.println("=== Low Stock Alerts ===");
ims.getLowStockAlerts().forEach(System.out::println);
System.out.println("\n=== Products in Electronics category ===");
ims.getProductsByCategory("Electronics").forEach(System.out::println);
System.out.println("\n=== Products between $50 and $200 ===");
ims.getProductsInPriceRange(50, 200).forEach(System.out::println);
System.out.println("\n=== Frequently bought with Laptop ===");
ims.getRelatedProducts("P100").forEach(System.out::println);
System.out.println("\n=== All products sorted by price (QuickSort) ===");
ims.getProductsSortedByPrice().forEach(System.out::println);
// Binary search demonstration
System.out.println("\n=== Binary search for product at $49.99 ===");
Product found = ims.binarySearchByPrice(ims.getProductsSortedByPrice(), 49.99);
System.out.println(found != null ? found : "Not found");
}
}
Key Data Structures and Algorithms Used:
Hash Table (ConcurrentHashMap): For O(1) product lookups by ID in a thread-safe manner
TreeSet (Red-Black Tree): To maintain products sorted by price
Graph (Adjacency List): To represent product relationships (frequently bought together)
Priority Queue (Min-Heap): For efficient low stock alerts
QuickSort: Alternative sorting algorithm for products by price
Binary Search: For efficient price-based searching in sorted arrays
Recursion: Used in the QuickSort implementation
Real-Time Features:
Concurrent Updates: Uses ConcurrentHashMap to handle simultaneous inventory updates
Low Stock Monitoring: Heap data structure provides efficient alerts
Fast Filtering: Multiple indexes (price tree, category hash) enable quick filtering
Relationship Management: Graph structure tracks product bundles
Efficient Sorting: Both TreeSet and QuickSort implementations provided for different use cases
No comments:
Post a Comment