lingz lingz - 3 months ago 7
Groovy Question

Java stream collectors in groovy error on Set::size

I'm trying to do a

SELECT MAX(COUNT DISTINCT field_x) FROM stream GROUP BY field_y;
in a groovy script using Java Streams / Collectors. Basically, I'd like a solution for
COUNT DISTINCT
, that I can then feed into
.max
.

I've been trying the solutions from this post: java 8 - stream, map and count distinct

But getting the error:

unexpected token: : @ line 65, column 114.
")}, Collectors.toSet()), Set::size).val


Groovy seems to be having a problem with
Set::size
and
Map::size
.

I've imported both
java.util.Map
and
java.util.Set
to no avail. Is this a problem with Groovy syntax / importing Java classes or a problem with how I'm using
Collectors
? For reference, I've merely tried to implement a forEach println on this map from the original post solution:

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


Apologies if this is more appropriate as a comment, but SO apparently requires more reputation to comment than to ask a question.

Answer

Unfortunately groovy does not accepts java method reference syntax, however you can use closures and rewrite it like this

Map<Integer, Integer> map = bids.stream().collect(
    groupingBy(
            {bid -> bid.bidderUserId},
            collectingAndThen(
                    mapping({bid -> bid.auctionId}, toSet()),
                    {set -> set.size()})));

Or (a bit shorter) using closure with implicit parameter and method pointer operator

Map<Integer, Integer> map = bids.stream().collect(
    groupingBy(
            {it.&getBidderUserId()},
            collectingAndThen(
                    mapping({it.&getAuctionId()}, toSet()),
                    {it.&size()})));

EDIT

Or even shorter (credits to @cfrick):

Map<Integer, Integer> map = bids.stream().collect(
    groupingBy(
            {it.bidderUserId},
            collectingAndThen(
                    mapping({it.auctionId}, toSet()),
                    {it.size()})));
Comments