Java Streams: Combining two collections into a map
<p>I have two Collections, a list of warehouse ids and a collection of widgets. Widgets exist in multiple warehouses in varying quantities:</p>

<pre><code>List&lt;Long&gt; warehouseIds;
List&lt;Widget&gt; widgets;
</code></pre>

<p>Here's an example defeinition of classes:</p>

<pre><code>public class Widget {
    public Collection&lt;Stock&gt; getStocks();
}

public class Stock {
    public Long getWarehouseId();
    public Integer getQuantity();
}
</code></pre>

<p>I want to use the Streams API to create a Map, where the warehouse ID is the key, and the value is a list of Widgets with the smallest quantity at a particular warehouse. Because multiple widgets could have the same quantity, we return a list.</p>

<p>For example, <strong>Warehouse 111</strong> has <strong>5</strong> qty of <strong>Widget A</strong>, <strong>5</strong> of <strong>Widget B</strong>, and <strong>8</strong> of <strong>Widget C</strong>. </p>

<p><strong>Warehouse 222</strong> has <strong>0</strong> qty of <strong>Widget A</strong>, <strong>5</strong> of <strong>Widget B</strong>, and <strong>5</strong> of <strong>Widget C</strong>
The Map returned would have the following entries:</p>

<p><code>111 =&gt; ['WidgetA', 'WidgetB']</code></p>

<p><code>222 =&gt; ['WidgetA']</code></p>

<p>Starting the setup of the Map with keys seems pretty easy, but I don't know how to structure the downstream reduction:</p>

<pre><code>warehouseIds.stream().collect(Collectors.groupingBy(
    Function::Identity,
    HashMap::new,
    ???...
</code></pre>

<p>I think the problem I'm having is reducing Widgets based on the stock warehouse Id, and not knowing how to return a Collector to create this list of Widgets. Here's how I would currently get the list of widgets with the smallest stock at a particular warehouse (represented by <strong>someWarehouseId</strong>):</p>

<pre><code>widgets.stream().collect(Collectors.groupingBy(
    (Widget w)-&gt;
        w.getStocks()
        //for a specific warehouse
        .stream().filter(stock-&gt;stock.getWarehouseId()==someWarehouseId)
        //Get the quantity of stocks for a widget
        .collect(Collectors.summingInt(Stock::getQuantity)),
    //Use a tree map so the keys are sorted
    TreeMap::new,
    //Get the first entry
    Collectors.toList())).firstEntry().getValue();
</code></pre>

<p>Separating this into two tasks using forEach on the warehouse list would make this job easy, but I am wondering if I can do this in a 'one-liner'.</p>