Real time Java Collections interview Questions with answers
Questions
- Which Java collection would you use to store invoices for fast lookup by invoiceId? Why?
- How would you remove duplicate invoices from a list?
- What is the difference between HashMap, TreeMap, and LinkedHashMap? Which one would you use for storing invoices and why?
- How would you sort invoices by date? Which collection would you use?
- What is the difference between a HashSet and a TreeSet? When would you use each?
- Why is HashMap preferred for storing invoices with invoiceId as the key?
- What is the time complexity of put(), get(), and remove() operations in a HashMap?
- What is the impact of choosing a bad hash function for invoice IDs in a HashMap?
- Which collection would you use to maintain invoices in sorted order by date?
- How does TreeSet ensure sorting? What are its advantages and disadvantages?
- How would you group invoices by partnerId using a Map?
- Can a HashMap store multiple invoices under the same partnerId? If so, how?
- How would you implement sorting of invoices using Comparator and Comparable?
Questions & Answers
- Which Java collection would you use to store invoices for fast lookup by invoiceId? Why?
Answer:
In my project, I used a HashMap<String, Invoice>, where the invoiceId was the key, and the corresponding Invoice object was the value.
Why?
- Fast Lookups: HashMap provides O(1) average time complexity for get() and put(), ensuring efficient retrieval of invoices by invoiceId.
- Efficient Storage: Unlike a list or array, a HashMap does not require scanning all elements to find a specific invoice.
- Avoids Duplicates: Since keys in a HashMap are unique, it prevents storing duplicate invoices with the same invoiceId.
Example from My Work Experience:
In our automated invoicing system, we needed quick access to invoices for reconciliation and dispute resolution. Using a HashMap significantly improved lookup speed compared to a list-based approach.
- How would you remove duplicate invoices from a list?
Answer:
I would use a HashSet to remove duplicate invoices based on invoiceId.
Approach:
- Create a Set to track unique invoice IDs.
- Use a LinkedHashSet to maintain insertion order while ensuring uniqueness.
- If a duplicate is found, ignore it.
Example from My Work Experience:
While developing an automated invoice processing feature, duplicate invoices were sometimes generated due to retries in AWS Lambda-based workflows. Using a HashSet eliminated duplicate invoices before processing.
Implementation:
Set<String> uniqueInvoiceIds = new HashSet<>();
List<Invoice> uniqueInvoices = new ArrayList<>();
for (Invoice invoice : invoices) {
if (uniqueInvoiceIds.add(invoice.getInvoiceId())) { // Returns false if duplicate
uniqueInvoices.add(invoice);
}
}
- What is the difference between HashMap, TreeMap, and LinkedHashMap? Which one would you use for storing invoices and why?
Collection Type | Ordering | Performance | Use Case |
HashMap | No order | O(1) for get() and put() | Fast lookups & storage |
TreeMap | Sorted by key (natural or custom) | O(log n) due to Red-Black tree | When sorted order is required |
LinkedHashMap | Maintains insertion order | Slightly slower than HashMap | When order of insertion matters |
Which one did I use?
I used a HashMap<String, Invoice> for fast invoice lookups.
- It provided O(1) lookup time, making it ideal for quickly retrieving invoices by invoiceId.
- If sorting was needed, I converted the HashMap into a TreeMap or sorted list when required.
- How would you sort invoices by date? Which collection would you use?
Answer:
I used a TreeSet<Invoice> with a custom comparator for sorting invoices by date.
Approach:
- TreeSet maintains sorted order automatically using a comparator.
- Ensures no duplicate invoices while maintaining sorting.
- If duplicate invoices exist, a List + Collections.sort() approach is better.
Example from My Work Experience:
In our pre-production invoicing environment, invoices needed to be sorted by date to ensure proper reconciliation. Using a TreeSet reduced the need for repeated sorting.
Implementation:
Set<Invoice> sortedInvoices = new TreeSet<>(Comparator.comparing(Invoice::getDate));
sortedInvoices.addAll(invoiceList); // Adds and sorts automatically
Alternatively, using a List:
invoiceList.sort(Comparator.comparing(Invoice::getDate));
- What is the difference between HashSet and TreeSet? When would you use each?
Feature | HashSet | TreeSet |
Ordering | No order | Sorted order |
Performance | O(1) for add, remove, contains | O(log n) for operations (Red-Black tree) |
Use Case | When order does not matter | When elements need to be sorted |
Which one did I use in my project?
- I used HashSet when removing duplicate invoices without needing order (fast performance).
- I used TreeSet when sorting invoices by date.
Example from My Work Experience:
- Removing duplicate invoices: Used HashSet for O(1) performance.
- Sorting invoices in reports: Used TreeSet to maintain chronological order.
- Why is HashMap preferred for storing invoices with invoiceId as the key?
Answer:
HashMap<String, Invoice> was preferred because:
- O(1) lookup time → Needed for fast invoice retrieval.
- Prevents duplicate keys → Ensures no duplicate invoices exist.
- Efficient memory usage → No need to store unnecessary indexes like in lists.
- Supports scalability → Handles large data efficiently without significant performance degradation.
Example from My Work Experience:
While developing the reseller onboarding automation, invoices needed to be retrieved instantly based on invoiceId. Using a HashMap ensured that invoices were accessed in constant time, significantly reducing processing delays.
Implementation in My Project:
Map<String, Invoice> invoiceMap = new HashMap<>();
invoiceMap.put(invoice.getInvoiceId(), invoice);
// Retrieving an invoice
Invoice invoice = invoiceMap.get(“INV12345”);
This approach helped avoid unnecessary iterations compared to a list-based search, which would have been O(n).
- What is the time complexity of put(), get(), and remove() operations in a HashMap?
Answer:
- Average case: O(1) → HashMap provides constant-time performance for put(), get(), and remove() because it uses hashing to store and retrieve elements.
- Worst case: O(n) → If too many hash collisions occur, elements are stored in a linked list or a red-black tree (from Java 8+). If a bucket has too many elements, searching becomes O(log n) (tree-based structure).
Example from My Work Experience:
When implementing proactive reconciliation-based invoicing, I used a HashMap for fast invoice lookups based on invoiceId. The O(1) retrieval time ensured high efficiency, even when processing thousands of invoices.
- What is the impact of choosing a bad hash function for invoice IDs in a HashMap?
Answer:
A bad hash function causes high collision rates, leading to:
- Performance degradation → Too many elements in the same bucket force operations to degrade from O(1) to O(n) (before Java 8) or O(log n) (with tree-buckets).
- Uneven distribution → Some buckets become overloaded while others remain empty, leading to inefficient memory usage.
- Increased rehashing frequency → Causes unnecessary performance overhead.
Example from My Work Experience:
While designing the Fuse Partner Portal invoice lookup system, I ensured invoiceId.hashCode() was evenly distributed to avoid excessive collisions. I tested the system with highly variable invoice IDs to validate performance.
- Which collection would you use to maintain invoices in sorted order by date?
Answer:
- TreeSet<Invoice> → If I need a sorted, unique collection of invoices.
- PriorityQueue<Invoice> → If I need a sorted collection but allow duplicates.
- List<Invoice> + Collections.sort() → If I receive invoices unsorted and sort them when needed.
Example from My Work Experience:
For pre-production invoice validation, I needed to process invoices chronologically. I used a TreeSet with a custom comparator to ensure that invoices remained sorted by date automatically.
Implementation:
Set<Invoice> sortedInvoices = new TreeSet<>(Comparator.comparing(Invoice::getDate));
sortedInvoices.addAll(invoiceList); // Automatically sorted
- How does TreeSet ensure sorting? What are its advantages and disadvantages?
Answer:
- TreeSet is based on a Red-Black Tree (self-balancing BST), ensuring O(log n) time complexity for add(), remove(), and contains().
- Elements are automatically sorted in ascending order based on Comparable or a custom Comparator.
Advantages:
Automatic sorting (no need for extra sorting operations).
No duplicate values (prevents duplicate invoices automatically).
Efficient O(log n) performance for insert, delete, and search.
Disadvantages:
❌ Slower than HashSet (O(log n) vs. O(1)).
❌ Cannot store duplicate invoices (if needed, PriorityQueue is better).
Example from My Work Experience:
In carbon feature set integration, invoice records needed to be sorted for audit reporting. A TreeSet ensured correct ordering without manual sorting operations.
- How would you group invoices by partnerId using a Map?
Answer:
I would use a HashMap<String, List<Invoice>>, where:
- Key → partnerId
- Value → A List<Invoice> containing all invoices for that partner.
Implementation:
Map<String, List<Invoice>> invoiceMap = new HashMap<>();
for (Invoice invoice : invoices) {
invoiceMap.computeIfAbsent(invoice.getPartnerId(), k -> new ArrayList<>()).add(invoice);
}
Example from My Work Experience:
For the reseller onboarding automation, invoices had to be grouped by partnerId for easier reconciliation. Using a HashMap allowed for fast grouping and quick access to partner-specific invoices.
- Can a HashMap store multiple invoices under the same partnerId? If so, how?
Answer:
Yes, a HashMap can store multiple invoices under the same partnerId by using a List<Invoice> as the value.
Implementation:
Map<String, List<Invoice>> partnerInvoices = new HashMap<>();
for (Invoice invoice : invoices) {
partnerInvoices.computeIfAbsent(invoice.getPartnerId(), k -> new ArrayList<>()).add(invoice);
}
Example from My Work Experience:
When developing the TAM (Technical Account Manager) Partner Portal, we needed to display all invoices for a given partner. Storing them as a List inside a HashMap allowed efficient grouping and retrieval.
- How would you implement sorting of invoices using Comparator and Comparable?
Answer:
- Use Comparable when sorting by a natural order (e.g., by date).
- Use Comparator for custom sorting logic (e.g., sort by amount, then by date).
Using Comparable: Sorting invoices by date (default order)
class Invoice implements Comparable<Invoice> {
private String invoiceId;
private LocalDate date;
@Override
public int compareTo(Invoice other) {
return this.date.compareTo(other.date); // Ascending order
}
}
Now, Collections.sort(invoices) will automatically sort invoices by date.
Using Comparator: Sorting invoices by amount, then by date
Comparator<Invoice> byAmountThenDate = Comparator
.comparing(Invoice::getAmount)
.thenComparing(Invoice::getDate);
Collections.sort(invoiceList, byAmountThenDate);
🔹 Advantage: Can sort dynamically without modifying the class structure.
Example from My Work Experience:
For partner billing reconciliation, invoices needed to be sorted first by amount and then by date to identify high-value invoices. Using Comparator made it flexible to apply different sorting rules.