Real time Java Collections interview Questions with answers

Questions

  1. Which Java collection would you use to store invoices for fast lookup by invoiceId? Why?
  2. How would you remove duplicate invoices from a list?
  3. What is the difference between HashMap, TreeMap, and LinkedHashMap? Which one would you use for storing invoices and why?
  4. How would you sort invoices by date? Which collection would you use?
  5. What is the difference between a HashSet and a TreeSet? When would you use each?
  6. Why is HashMap preferred for storing invoices with invoiceId as the key?
  7. What is the time complexity of put(), get(), and remove() operations in a HashMap?
  8. What is the impact of choosing a bad hash function for invoice IDs in a HashMap?
  9. Which collection would you use to maintain invoices in sorted order by date?
  10. How does TreeSet ensure sorting? What are its advantages and disadvantages?
  11. How would you group invoices by partnerId using a Map?
  12. Can a HashMap store multiple invoices under the same partnerId? If so, how?
  13. How would you implement sorting of invoices using Comparator and Comparable?

 

Questions & Answers

  1. 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.

 

  1. How would you remove duplicate invoices from a list?

Answer:
I would use a HashSet to remove duplicate invoices based on invoiceId.

Approach:

  1. Create a Set to track unique invoice IDs.
  2. Use a LinkedHashSet to maintain insertion order while ensuring uniqueness.
  3. 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);

    }

}

 

  1. 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.

 

  1. 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));

 

  1. 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.

 

  1. Why is HashMap preferred for storing invoices with invoiceId as the key?

Answer:
HashMap<String, Invoice> was preferred because:

  1. O(1) lookup time → Needed for fast invoice retrieval.
  2. Prevents duplicate keys → Ensures no duplicate invoices exist.
  3. Efficient memory usage → No need to store unnecessary indexes like in lists.
  4. 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).

 

  1. 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.

 

  1. 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:

  1. 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).
  2. Uneven distribution → Some buckets become overloaded while others remain empty, leading to inefficient memory usage.
  3. 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.

 

  1. 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

 

  1. 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.

 

  1. 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.

 

  1. 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.

 

  1. 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.