我有两个集合,一个仓库ID列表和一组小部件。小部件存在于不同数量的多个仓库中:
List<Long> warehouseIds;
List<Widget> widgets;
以下是类的定义示例:
public class Widget {
public Collection<Stock> getStocks();
}
public class Stock {
public Long getWarehouseId();
public Integer getQuantity();
}
我想使用Streams API创建一个Map,其中仓库ID是密钥,值是特定仓库中数量最小的Widgets列表。因为多个小部件可以具有相同的数量,所以我们返回一个列表。
例如,仓库111 5 数量小工具A , 5 小工具B ,以及小部件C 的 8 。
仓库222 0 数量小工具A , 5 小工具B 和 5 Widget C 返回的地图将包含以下条目:
111 => ['WidgetA', 'WidgetB']
222 => ['WidgetA']
使用键开始设置Map似乎很容易,但我不知道如何构建下游缩减:
warehouseIds.stream().collect(Collectors.groupingBy(
Function::Identity,
HashMap::new,
???...
我认为我遇到的问题是根据库存仓库ID减少小部件,而不知道如何返回收集器来创建此小部件列表。以下是我目前如何获得特定仓库中库存最小的小部件列表(由 someWarehouseId 表示):
widgets.stream().collect(Collectors.groupingBy(
(Widget w)->
w.getStocks()
//for a specific warehouse
.stream().filter(stock->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();
使用仓库清单上的forEach将其分成两个任务会使这项工作变得简单,但我想知道我是否可以在“单行”中执行此操作。
答案 0 :(得分:4)
要解决此问题,我们需要使用比使用public class Values
{
public Values(int value)
{
this.SomeValue = value;
}
public int SomeValue { get; }
}
// Register as
container.RegisterSingleton<Values>(() => new Values(1));
更合适的方法来选择数量最小的值。
考虑以下方法:
TreeMap
个初始小部件。我们需要对每个小部件的库存进行一些处理,但我们还需要保持小部件。让我Stream<Widget>
flatMap
成Stream<Widget>
:新流将由我们拥有的每个Stream<Map.Entry<Stock, Widget>>
组成,并包含相应的Stock
。Widget
列表中包含Map.Entry<Stock, Widget>
库存的warehouseId
。warehouseIds
的{{1}}对该流进行分组。因此,我们使用Collectors.groupingBy(classifier, downstream)
,其中分类器返回warehouseId
。Stock
的{{1}}元素,我们只需要保留库存数量最少的元素。没有内置的收集器,让我们使用MoreCollectors.minAll(comparator, downstream)
库中的StreamEx。如果您不想使用该库,我已将其代码提取到此答案中并将使用它。warehouseId
中每只股票的数量。这样可以确保我们为固定Map.Entry<Stock, Widget>
保留最低数量的元素。下游收集器用于减少收集的元素。在这种情况下,我们只想保留小部件,因此我们使用Collectors.mapping(mapper, downstream)
,映射器从warehouseId
返回小部件,下游收集器收集到Collectors.toList()
的列表。示例代码:
Map.Entry<Stock, Widget>
使用以下warehouseId
收集器:
Map.Entry<Stock, Widget>