java 8 – 流,地图和计数不同
我第一次尝试java 8流…
我有一个对象Bid,它代表用户对拍卖中商品的出价。 我有一个出价列表,我想制作一张地图,其中包含用户出价的拍卖数量(不同)。
这是我的看法:
bids.stream() .collect( Collectors.groupingBy( bid -> Bid::getBidderUserId, mapping(Bid::getAuctionId, Collectors.toSet()) ) ).entrySet().stream().collect(Collectors.toMap( e-> e.getKey(),e -> e.getValue().size()) );
它工作,但我觉得我在作弊,因为我流式传输地图的入口集,而不是在初始流上做一个操作…必须是一个更正确的方式这样做,但我无法想象出来…
谢谢
您可以执行两次groupingBy
:
Map> map = bids.stream().collect( groupingBy(Bid::getBidderUserId, groupingBy(Bid::getAuctionId, counting())));
这样,每个用户在每次竞价中都会有多少出价。 因此内部地图的大小是用户参与的拍卖数量。 如果您不需要其他信息,可以执行以下操作:
Map map = bids.stream().collect( groupingBy( Bid::getBidderUserId, collectingAndThen( groupingBy(Bid::getAuctionId, counting()), Map::size)));
这正是您所需要的:将用户映射到用户参与的拍卖数量。
更新:还有类似的解决方案,更贴近您的示例:
Map map = bids.stream().collect( groupingBy( Bid::getBidderUserId, collectingAndThen( mapping(Bid::getAuctionId, toSet()), Set::size)));
Tagir Valeev的答案是正确的(+1)。 这是另一个使用您自己的groupBy下游收集器完全相同的:
Map map = bids.stream().collect( Collectors.groupingBy(Bid::getBidderUserId, new Collector, Long>() { @Override public Supplier> supplier() { return HashSet::new; } @Override public BiConsumer, Bid> accumulator() { return (s, b) -> s.add(b.getAuctionId()); } @Override public BinaryOperator> combiner() { return (s1, s2) -> { s1.addAll(s2); return s1; }; } @Override public Function, Long> finisher() { return (s) -> Long.valueOf(s.size()); } @Override public Set characteristics() { return Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH)); } }));