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())
);
Это работает, но я чувствую, что я обманываю, потому что я потоплю наборы записей на карте, вместо того, чтобы делать манипуляции с начальным потоком... должен быть более правильным способом сделать это, но я не мог "Не понимаю".
Спасибо
Ответы
Ответ 1
Вы можете выполнить 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)));
Ответ 2
Ответ Тагира Валеева правильный (+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));
}
}));