Somasundaram Sekar
Somasundaram Sekar

Reputation: 5524

java.util.stream.Collectors with EnumSet Stream

I'm trying to use in place of bitmask below is the code

public static Set<Amenities> fromBitFlags(int bitFlag) {
    return ALL_OPTS.stream().filter(a -> (a.ameityId & bitFlag) > 0).collect(Collectors.toSet());
}

I would like to return EnumSet instead of a plain set(dont want to loose out on EnumSet's usefulness just because of casting).

Need some directions on how to create a Custom Collector to collect EnumSet.

Upvotes: 48

Views: 19089

Answers (2)

charlie
charlie

Reputation: 1527

If you'd like to have a reusable toEnumSet() collector:

<E extends Enum<E>> Collector<E, ?, EnumSet<E>> toEnumSet() {
    return Collectors.collectingAndThen(Collectors.toSet(), EnumSet::copyOf);
}

EnumSet<Amenities> fromBitFlags(int bitFlag) {
    return ALL_OPTS.stream()
            .filter(a -> (a.ameityId & bitFlag) > 0)
            .collect(toEnumSet()));
}

If you don't need to reuse it, you can of course in-line it:

EnumSet<Amenities> fromBitFlags(int bitFlag) {
    return ALL_OPTS.stream()
            .filter(a -> (a.ameityId & bitFlag) > 0)
            .collect(collectingAndThen(toSet(), EnumSet::copyOf));
}

(assuming static imports from Collectors)


Alternatively, you can just wrap your original Set<Amenities> result:

EnumSet<Amenities> fromBitFlags(int bitFlag) {
    return EnumSet.copyOf(
            ALL_OPTS.stream()
                    .filter(a -> (a.ameityId & bitFlag) > 0)
                    .collect(toSet()));
}

Just for fun of it — you can also use reduce:

            .reduce(EnumSet.noneOf(Amenities.class), // identity
                    EnumSet::add, // accumulator
                    EnumSet::addAll)); // combiner

but that's hard to reuse, so maybe better a reducing collector:

            .collect(reducing(
                    EnumSet.noneOf(Amenities.class), // identity
                    EnumSet::of, // mapper
                    EnumSet::addAll)); // combiner

Upvotes: 0

Tagir Valeev
Tagir Valeev

Reputation: 100209

You may use toCollection(Supplier):

return ALL_OPTS.stream().filter(a -> (a.ameityId & bitFlag) > 0)
               .collect(Collectors.toCollection(() -> EnumSet.noneOf(Amenities.class)));

The toCollection method receives a lambda which should create an empty collection to store the result. Here we create empty EnumSet using EnumSet.noneOf call. Note that for EnumSet you must always specify (implicitly or explicitly) which enum is this set for.

Upvotes: 94

Related Questions