Java8-流、映射和计数不同
我第一次尝试使用Java8流 我有一个对象出价,它表示用户在拍卖中对某个项目的出价。我有一个出价列表,我想制作一张地图,统计用户出价的(不同的)拍卖次数 这是我对它的看法:Java8-流、映射和计数不同,java,java-8,java-stream,Java,Java 8,Java Stream,我第一次尝试使用Java8流 我有一个对象出价,它表示用户在拍卖中对某个项目的出价。我有一个出价列表,我想制作一张地图,统计用户出价的(不同的)拍卖次数 这是我对它的看法: bids.stream() .collect( Collectors.groupingBy( bid -> Bid::getBidderUserId, mapping(Bid::getAuctionI
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())
);
这是可行的,但我觉得我在作弊,因为我流化了地图的条目集,而不是对初始流进行操作。。。这肯定是一个更正确的方法,但我想不出来
谢谢您可以执行两次分组:
Map<Integer, Map<Integer, Long>> map = bids.stream().collect(
groupingBy(Bid::getBidderUserId,
groupingBy(Bid::getAuctionId, counting())));
Map Map=bids.stream().collect(
groupingBy(Bid::getBidderUserId,
分组方式(Bid::getAuctionId,counting());
这样,您就可以知道每个用户在每次拍卖中有多少次出价。因此,内部地图的大小是用户参与拍卖的次数。如果不需要其他信息,可以执行以下操作:
Map<Integer, Integer> map = bids.stream().collect(
groupingBy(
Bid::getBidderUserId,
collectingAndThen(
groupingBy(Bid::getAuctionId, counting()),
Map::size)));
Map Map=bids.stream().collect(
分组依据(
Bid::getBidderUserId,
收集然后(
groupingBy(Bid::getAuctionId,counting()),
地图:大小),;
这正是您需要的:将用户映射到用户参与的拍卖数量
更新:还有类似的解决方案更接近您的示例:
Map<Integer, Integer> map = bids.stream().collect(
groupingBy(
Bid::getBidderUserId,
collectingAndThen(
mapping(Bid::getAuctionId, toSet()),
Set::size)));
Map Map=bids.stream().collect(
分组依据(
Bid::getBidderUserId,
收集然后(
映射(Bid::getAuctionId,toSet()),
Set::size));
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));
}
}));
Map Map=bids.stream().collect(
Collectors.groupingBy(Bid::getBidderUserId,
新收集器(){
@凌驾
公共供应商(){
返回HashSet::new;
}
@凌驾
公共双消费者累加器(){
返回(s,b)->s.add(b.getAuctionId());
}
@凌驾
公共二进制运算符组合器(){
返回(s1、s2)->{
s1.addAll(s2);
返回s1;
};
}
@凌驾
公共函数完成器(){
return(s)->Long.valueOf(s.size());
}
@凌驾
公共集特征(){
返回Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,Collector.Characteristics.IDENTITY_FINISH));
}
}));
您能将您的投标对象声明包括在内吗?是的,我删除了我的评论,因为我意识到它应该是您刚才添加的内容。我在想之前就发帖了。太棒了!这正是我想要的,收集然后
方法,我不知道如何使用它。非常感谢:)