45

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.

Somasundaram Sekar
  • 5,244
  • 6
  • 43
  • 85

1 Answers1

86

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.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
  • Thanks a lot, would be really helpful if you could explain this lambda in brief `() -> EnumSet.noneOf(Amenities.class)` , how this creates a Supplier that can automatically call `EnumSet.add()` – Somasundaram Sekar Feb 03 '16 at 13:55
  • 1
    @SomasundaramSekar, added some explanation. Hopefully this helps. – Tagir Valeev Feb 03 '16 at 14:33
  • 6
    Mind the alternative of `EnumSet s=EnumSet.copyOf(ALL_OPTS); s.removeIf(a -> (a.ameityId & bitFlag) <= 0);`… – Holger Feb 03 '16 at 15:53
  • 1
    @Holger that's a bad alternative, as it might throw an unnecessary `IllegalArgumentException` if the Collection ALL_OPTS is empty and not an instance of `EnumSet`. – qutax Nov 27 '20 at 09:29
  • 2
    @qutax the naming style suggests that `ALL_OPTS` is a constant containing all options, with a predictable non-empty content. The OP’s concerns about losing EnumSet's usefulness also suggest that `ALL_OPTS` is an `EnumSet` in the first place. Of course, it would be easy to fix if that’s not the case. – Holger Nov 27 '20 at 09:50
  • 1
    If ALL_OPTS is an `EnumSet`, chances are high that its not actually a constant, as `JumboEnumSet` and `RegularEnumSet` are both mutable and I don't think that the OP implemented an unmodifiable implementation of `EnumSet`. And yes, for this special case it is likely that ALL_OPTS is not empty (even though depending on the actual case ALL_OPTS could be none opts at all, I guess). But as people often copy-and-paste code found on SO, even if it doesn't match their case 100%, I felt the need to point out the chance of producing an Exception when using your — in my opinion bad — alternative. – qutax Nov 27 '20 at 10:00
  • 2
    @qutax if `ALL_OPTS` is an `EnumSet`, it doesn’t matter whether it is empty, as `EnumSet.copyOf(ALL_OPTS)` will always work. In fact, I’d consider the case that `ALL_OPTS` is empty worth producing an exception, rather than proceeding with an empty result set. – Holger Nov 04 '22 at 12:20
  • @Holger's alternative is fine. It's highly unlikely that `ALL_OPTS` is an empty non-`EnumSet`. If it is, that's probably a bug, and I *want* to get an exception. Anyway, in most cases you probably don't need `ALL_OPTS` anyway (premature optimization?) and you can replace `EnumSet.copyOf(ALL_OPTS)` by `EnumSet.allOf(Amenities.class)`. – jcsahnwaldt Reinstate Monica Mar 09 '23 at 11:55