Katkat

Java Core Deep Dive: Concurrent Collections and Java 8 Features

J.P. MorganSoftware Engineer · Onsite

Last updated

This question tests your understanding of thread-safety in Java collections and your ability to refactor imperative code into functional Java 8 style streams.

Part 1: Concurrent Collections

Explain the difference between java.util.concurrent.ConcurrentHashMap and java.util.Collections.synchronizedMap(new HashMap()). Specifically, discuss how each implementation handles locking (e.g., granularity of locks) and how their iterators behave in terms of 'fail-fast' versus 'weakly consistent' properties when the underlying map is modified concurrently.

Part 2: Java 8 Streams and Optional

You are given a list of Transaction objects. Each transaction has a String traderId, int amount, and String currency.

Write a method using the Java Stream API that returns a Map> where the key is the traderId and the value is the Optional containing the transaction with the highest amount for that trader. If a trader has no transactions, the map should either omit them or contain an Optional.empty().

class Transaction {
    String traderId;
    int amount;
    String currency;
    // Getters and constructor omitted
}

Constraints

  • Use Collectors.groupingBy.
  • Use Collectors.maxBy for finding the transaction with the largest amount.
  • Ensure the code handles potentially empty input lists gracefully.

Example

Input: [{"A", 100, "USD"}, {"A", 200, "USD"}, {"B", 50, "EUR"}] Output: {"A": Optional[{"A", 200, "USD"}], "B": Optional[{"B", 50, "EUR"}]}

Hints

Hint 1

Consider the difference between a global lock on the entire map versus the bucket-level locking or CAS operations used in modern concurrent maps.

Hint 2

Recall that 'weakly consistent' iterators do not throw ConcurrentModificationException and reflect the state of the map at the time of iterator creation.

Hint 3

For the Stream task, look into the `Collectors.groupingBy` overload that accepts a downstream collector to perform the reduction on the grouped values.

Follow-up questions

  • How does the memory model in Java ensure that changes made by one thread in a ConcurrentHashMap are visible to other threads?
  • What are the performance implications of using parallel streams versus sequential streams when processing large datasets?
  • When should you prefer Optional over returning null, and what are the common pitfalls of using Optional as a field in a class?