Code Logo

Catalog Price Merge with toMap()

Published at22 Apr 2026
Stream API Medium 0 views
Like0

A school cooperative updates its product catalog throughout the week as different staff members report new prices. The raw update list arrives as strings in the format "item:price". Sometimes the same item appears more than once because a later report corrected the earlier price.

The office does not want to keep all duplicate entries. It wants one final lookup map where each item name appears only once, and if the same item is reported multiple times, the highest reported price should be kept. That rule is important because the staff wants the final table to reflect the most expensive known value rather than accidentally preserving an outdated lower number.

Your task is to return a Map<String, Integer> built from the catalog entry list. Each entry must be parsed, converted into key-value form, and merged correctly when duplicates exist.

For example, if the input is ["pen:10", "book:20", "pen:12"], the result should be a map where pen has value 12 and book has value 20. The item pen appears twice, so the higher price wins. If every item appears only once, the map is just a straightforward conversion from strings into entries.

This is a medium Stream API challenge because the stream does more than one simple transformation. It needs to parse text, convert the numeric part into an integer, and apply a merge function while collecting. That combination is exactly where Collectors.toMap() becomes more interesting than a basic list pipeline.

Example Input & Output

Example 1
Input
entries = ["marker:15"]
Output
{"marker": 15}
Explanation

A one-entry list still becomes a one-entry map.

Example 2
Input
entries = ["glue:8", "paper:5", "glue:7"]
Output
{"glue": 8, "paper": 5}
Explanation

If a later duplicate has a lower price, the higher earlier value should remain.

Example 3
Input
entries = ["pen:10", "book:20", "pen:12"]
Output
{"pen": 12, "book": 20}
Explanation

Duplicate item names are merged by keeping the higher price.

Algorithm Flow

Recommendation Algorithm Flow for Catalog Price Merge with toMap()
Recommendation Algorithm Flow for Catalog Price Merge with toMap()

Solution Approach

This problem is centered on Collectors.toMap(). The basic idea is to convert each raw catalog string into a key-value pair, then let the collector build the final map. The twist is that duplicate keys can appear, so the stream must also provide a merge rule.

The first step is parsing. An entry such as "pen:12" needs to become key "pen" and value 12. Once those two pieces can be extracted, toMap() can use one function for the key and one for the value.

The most important part is the third argument, the merge function. Because the same item may appear more than once, Java needs to know what to do when two values collide. In this challenge, the rule is to keep the higher price, so Integer::max is a perfect fit.

A stream solution can look like this:

return entries.stream()
    .map(entry -> entry.split(":"))
    .collect(Collectors.toMap(
        parts -> parts[0],
        parts -> Integer.parseInt(parts[1]),
        Integer::max,
        LinkedHashMap::new
    ));

This pipeline parses each line, builds the map entries, and resolves duplicates in one collector. Using LinkedHashMap also keeps the insertion order of first appearance, which can make the resulting map easier to inspect.

This feels medium because a plain toMap() with unique keys is much simpler. Here you also need to think about duplicate handling and parsing, and both details matter for correctness.

The runtime is O(n) for n catalog entries, assuming normal map operations. The main lesson is that toMap() becomes especially powerful when you pair it with an explicit merge strategy.

Best Answers

java - Approach 1
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

class Solution {
    public static Map<String, Integer> buildPriceMap(List<String> entries) {
        return entries.stream()
                .map(entry -> entry.split(":"))
                .collect(Collectors.toMap(
                        parts -> parts[0],
                        parts -> Integer.parseInt(parts[1]),
                        Integer::max,
                        LinkedHashMap::new
                ));
    }
}