collections

Collections & Arrays: Utility Puzzles

šŸ”¹ Collections Utility Puzzles (Deep Dive, Interview-Ready)

Technical interviews often include rapid-fire "puzzle" questions regarding the java.util.Collections and java.util.Arrays utility classes. Knowing the subtle memory implications and one-liner tricks can immediately elevate you from a junior to a senior candidate.


šŸ“Œ 1. Returning Empty Collections Safely

Scenario: You have a method that returns a List<User>. No users are found. Do you return null or a new empty list?

āŒ The Wrong Ways

// 1. Returning Null (Causes NullPointerExceptions for callers) return null; // 2. Wasting Memory (Creates unnecessary objects) return new ArrayList<>();

āœ… The Senior Way

Always return an empty collection using the Collections utility methods (or Java 9+ factory methods).

return Collections.emptyList(); // Pre-Java 9 return List.of(); // Java 9+

šŸ‘‰ Why it's better: Collections.emptyList() returns a singleton, immutable instance. No matter how many times you call it across your entire application, it never allocates new memory on the heap. It is perfectly memory efficient.


šŸ“Œ 2. Unmodifiable (Read-Only) Collections

Scenario: You want to pass your internal List to a third-party library, but you don't want them to accidentally (or maliciously) add or remove items.

List<String> myInternalData = new ArrayList<>(Arrays.asList("A", "B", "C")); // Wrap it in an unmodifiable view List<String> safeList = Collections.unmodifiableList(myInternalData);

šŸ‘‰ The Gotcha: unmodifiableList is just a wrapper around the original list. If you change myInternalData (the source), safeList will reflect those changes immediately. However, if anyone tries to call safeList.add(), it will throw an UnsupportedOperationException.


šŸ“Œ 3. Reversing a Map (Value to Key)

Scenario: You have a Map<String, String> mapping Employee ID to Email. You suddenly need to look up an Employee ID by their Email.

šŸ”ø Modern Java (Streams)

You can flip a Map in one clean stream operation, assuming all values are unique.

Map<String, String> idToEmail = Map.of("101", "alice@test.com", "102", "bob@test.com"); Map<String, String> emailToId = idToEmail.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));

šŸ‘‰ The Gotcha: If multiple keys have the same value (e.g., two employees with the same email), the collector will crash with an IllegalStateException. You must handle duplicates if they exist:

// Keeps the first key it finds in case of a collision .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (oldKey, newKey) -> oldKey));

šŸ“Œ 4. Creating Fixed-Size Arrays (The Arrays.asList Trap)

Scenario: Initializing a list quickly.

List<String> list = Arrays.asList("A", "B", "C");

šŸ‘‰ The Trap: The list returned by Arrays.asList() is backed by the original array. It is fixed-size.

  • list.set(0, "Z") -> āœ… Works (changes the underlying array).
  • list.add("D") -> āŒ Crashes with UnsupportedOperationException.

If you need a fully dynamic, modifiable list, you must wrap it:

List<String> dynamicList = new ArrayList<>(Arrays.asList("A", "B", "C"));

šŸ“Œ 5. Array to Collection / Collection to Array

Converting back and forth is a staple of Java development.

šŸ”ø Collection to Array

Always pass an empty array of the correct type to the toArray method to avoid ClassCastExceptions.

List<String> list = List.of("Apple", "Banana"); // Correct way (allocates exactly the right size) String[] arr = list.toArray(new String[0]);

šŸ”ø Array to Collection

String[] arr = {"Apple", "Banana"}; List<String> list = new ArrayList<>(Arrays.asList(arr)); // Modifiable

šŸ”„ Interview Gold Statement

"When asked to return empty collections, I always use Collections.emptyList() or Java 9's List.of() because they return immutable singleton instances, completely eliminating heap memory overhead compared to new ArrayList<>(). Furthermore, when converting arrays to lists using Arrays.asList(), I am always cautious because the resulting list is fixed-size and backed by the original array; it must be explicitly wrapped in a new ArrayList<>() if dynamic resizing is required."

Collections & Arrays: Utility Puzzles | DevExCode