2015-05-17 43 views
11

我第一次尝试java 8流...java 8 - 流,地图和数量不同

我有一个对象投标,它表示一个用户在拍卖中的一个项目的投标。我有一个出价清单,我想制作一张地图,记录用户进行了多少次(不同的)拍卖。

这是我对吧:

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()) 
     ); 

它的工作原理,但我觉得我欺骗,因为我流的入口设置地图的,而不是在初始流做处理。 ..必须这样做的一个比较正确的做法,但我无法弄清楚......

感谢

+3

您能否包含您的出价对象声明? – Nick

回答

15

可以执行groupingBy两次:

Map<Integer, Map<Integer, Long>> map = bids.stream().collect(
     groupingBy(Bid::getBidderUserId, 
       groupingBy(Bid::getAuctionId, counting()))); 

通过这种方式,您可以为每个用户在每次拍卖中获得多少出价。所以内部地图的大小就是用户参与的拍卖数量。如果您不需要附加信息,您可以这样做:

Map<Integer, Integer> map = bids.stream().collect(
     groupingBy(
       Bid::getBidderUserId, 
       collectingAndThen(
         groupingBy(Bid::getAuctionId, counting()), 
         Map::size))); 

这正是您需要的:用户映射到用户参与的拍卖数量。

更新:这里还有类似的解决方案,它是更接近你的例子:

Map<Integer, Integer> map = bids.stream().collect(
     groupingBy(
       Bid::getBidderUserId, 
       collectingAndThen(
         mapping(Bid::getAuctionId, toSet()), 
         Set::size))); 
+1

是的,我删除了我的评论,因为我意识到它应该是你刚才添加的。我在发帖之前想。 – Radiodef

+3

非常好!这正是我正在寻找的'collectAndThen'方法,我无法弄清楚如何使用。非常感谢 :) – Zemer

0

Tagir Valeev的答案是正确的(+1)。这是另一个使用您自己的下游收集器为groupBy完全相同:

Map<Integer, Long> map = bids.stream().collect(
       Collectors.groupingBy(Bid::getBidderUserId, 
            new Collector<Bid, Set<Integer>, Long>() { 

     @Override 
     public Supplier<Set<Integer>> supplier() { 
      return HashSet::new; 
     } 

     @Override 
     public BiConsumer<Set<Integer>, Bid> accumulator() { 
      return (s, b) -> s.add(b.getAuctionId()); 
     } 

     @Override 
     public BinaryOperator<Set<Integer>> combiner() { 
      return (s1, s2) -> { 
       s1.addAll(s2); 
       return s1; 
      }; 
     } 

     @Override 
     public Function<Set<Integer>, Long> finisher() { 
      return (s) -> Long.valueOf(s.size()); 
     } 

     @Override 
     public Set<java.util.stream.Collector.Characteristics> characteristics() { 
      return Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH)); 
     } 
    }));