ImmutableEnumSet ? best practices?

3,714 views
Skip to first unread message

fishtoprecords

unread,
Aug 11, 2010, 4:31:33 PM8/11/10
to guava-discuss
It sure looks like the JDK's EnumSet, which is claimed as being fine
for public static final sets of enums. But it is not Immutable.

The standard approach is to wrap it in Collections.unmodifiableSet()
but then you lose the generic type safety.

public enum PublicationStatus {
/** inactive and archived */
archived,
/** active usage done */
completed,
;
//public static final Set<PublicationStatus> ALL =
//
Collections.unmodifiableSet(EnumSet.allOf(PublicationStatus.class));
public static final EnumSet<PublicationStatus> ALL =
ImmutableSet.copyOf(EnumSet.allOf(PublicationStatus.class));

I assume that the ImmutableEnumSet was considered and not implemented,
while I'd love to know the rationale. But more to the point today,
what is the best practice today?

Thanks
Pat

Jared Levy

unread,
Aug 11, 2010, 4:43:38 PM8/11/10
to guava-...@googlegroups.com
You can use the Sets.immutableEnumSet() methods to create an immutable set of Enums. Those methods provide immutability and the performance of an EnumSet, since the implementation is a wrapper around an EnumSet.

Those method are a little difficult to find. Maybe the ImmutableSet Javadoc should mention them.



--
guava-...@googlegroups.com.
http://groups.google.com/group/guava-discuss?hl=en
unsubscribe: guava-discus...@googlegroups.com

This list is for discussion; for help, post to Stack Overflow instead:
http://stackoverflow.com/questions/ask
Use the tag "guava".

Pat Farrell

unread,
Aug 11, 2010, 8:48:46 PM8/11/10
to guava-...@googlegroups.com
On Wed, Aug 11, 2010 at 4:43 PM, Jared Levy <jared....@gmail.com> wrote:
You can use the Sets.immutableEnumSet() methods to create an immutable set of Enums. Those methods provide immutability and the performance of an EnumSet, since the implementation is a wrapper around an EnumSet.

Those method are a little difficult to find. Maybe the ImmutableSet Javadoc should mention them.

Javadocs pointers would sure help.

I'm just making random changes trying to find something that will compile.

First line compiles but loses type safety and member functions that are the point. Second won't compile.

public static final Set<PublicationStatus> ALL =  Sets.immutableEnumSet(EnumSet.allOf(PublicationStatus.class));
public static final EnumSet<PublicationStatus> ACTIVE = 
              (EnumSet<PublicationStatus>) Sets.immutableEnumSet(EnumSet.range(never, partial));

How do I get a result that is a EnumSet<PublicationStatus>  ?

Thanks
 

Jared Levy

unread,
Aug 11, 2010, 9:54:22 PM8/11/10
to guava-...@googlegroups.com
Why do you want an EnumSet? Besides the standard Set methods, an EnumSet just has static factory methods and clone(). 



Pat Farrell

unread,
Aug 11, 2010, 10:20:52 PM8/11/10
to guava-...@googlegroups.com
On Wed, Aug 11, 2010 at 9:54 PM, Jared Levy <jared....@gmail.com> wrote:
Why do you want an EnumSet? Besides the standard Set methods, an EnumSet just has static factory methods and clone(). 



Why do I want the compiler to generate type-safe classes? Isn't that obvious, type safe is good in my religion.

The range() factory looks handy and elegant. Especially for a for loop
 
But it looks as if the JDK lost interest in it, to be useful, it should have more real member functions. And given that I can't get Guava to do a decent job of creating static, Immutable EnumSet instances with proper <generic> safety, perhaps its not worth the trouble.


Tobias Thierer

unread,
Aug 11, 2010, 10:35:09 PM8/11/10
to guava-...@googlegroups.com
On Thu, Aug 12, 2010 at 12:20 PM, Pat Farrell <pat2...@gmail.com> wrote:
On Wed, Aug 11, 2010 at 9:54 PM, Jared Levy <jared....@gmail.com> wrote:
Why do you want an EnumSet? Besides the standard Set methods, an EnumSet just has static factory methods and clone(). 



Why do I want the compiler to generate type-safe classes? Isn't that obvious, type safe is good in my religion.

What exactly do you mean with type-safe here? The Set is still typesafe with respect to its elements.

As for the type of the Set itself, my religion is: write to an interface, not an implementation. It shouldn't matter what exact kind of Set<MyEnum> you have, your code shouldn't depend on it.
 

The range() factory looks handy and elegant. Especially for a for loop

range() is *static*. To invoke range(), you say EnumSet.range(foo, bar). It has nothing to do with any EnumSet (or other Set) *instance* you may have.

 
But it looks as if the JDK lost interest in it, to be useful, it should have more real member functions. And given that I can't get Guava to do a decent job of creating static, Immutable EnumSet instances with proper <generic> safety, perhaps its not worth the trouble.

What are you talking about? EnumSet *does* have generic type safety.   As for "The JDK lost interest in it", what kind of nonstatic functions can you think of that an EnumSet could provide but a normal Set couldn't?

Tobias

Pat Farrell

unread,
Aug 11, 2010, 11:44:08 PM8/11/10
to guava-...@googlegroups.com
What exactly do you mean with type-safe here? The Set is still typesafe with respect to its elements.


As I wrote up thread,  

public static final EnumSet<PublicationStatus> ACTIVE = 
             Sets.immutableEnumSet(EnumSet.range(never, partial));

does not compile. You have to declare it as just a Set.
When you only have the Set, you can't use any EnumSet member functions.
Granted, the class is mostly brain dead, it doesn't have a lot of useful member functions.

I'd love some non-static functions for range, complement, iteration, etc. And the main Set declaration has no natural order, and there are times when the order (declaration in the source code) is a useful order that you must lose when you just implement Set<foo>


Tobias Thierer

unread,
Aug 12, 2010, 12:13:12 AM8/12/10
to guava-...@googlegroups.com
On Thu, Aug 12, 2010 at 1:44 PM, Pat Farrell <pat2...@gmail.com> wrote:
What exactly do you mean with type-safe here? The Set is still typesafe with respect to its elements.


As I wrote up thread,  

public static final EnumSet<PublicationStatus> ACTIVE = 
             Sets.immutableEnumSet(EnumSet.range(never, partial));

does not compile. You have to declare it as just a Set.

Yes, and so far I have seen no argument that convinces me why that would be a bad idea.
 
When you only have the Set, you can't use any EnumSet member functions.
Granted, the class is mostly brain dead, it doesn't have a lot of useful member functions.

As Jared has already pointed out, EnumSet has NO public member functions in addition to Set.  EnumSet implements Cloneable, which however you don't need for an immutable Set because immutable values can be freely shared and don't need to be copied. 

The only advantage of typing it as EnumSet that I can see is that you'd be able to pass it to EnumSet.complementOf() - but see below for how to construct the complement of a Sets.immutableEnumSet().


I'd love some non-static functions for range, complement, iteration, etc.

EnumSet.complement() is not public, so that doesn't really count, and you should be able to construct a complement using

   Sets.immutableEnumSet(Sets.complementOf(enumSet))

Also, the iteration order in Sets.immutableEnumSet() is defined.

If you were after a SortedSet, EnumSet doesn't implement that interface either.

As for range: I'm guessing you mean something that returns the intersection between EnumSet.range() and some other EnumSet. Such a function might be useful, but it doesn't exist on EnumSet either. You'll have to do:

 Sets.immutableEnumSet(Sets.intersection(enumSet, EnumSet.range(a,b)));

which will require O(size of result set) time.
 
And the main Set declaration has no natural order, and there are times when the order (declaration in the source code) is a useful order that you must lose when you just implement Set<foo>

Most implementations of Set<Foo> actually guarantee order - LinkedHashSet does, TreeSet does, EnumSet does, and the Set returned from Sets.immutableEnumSet() does as well.

Cheers,

Tobias

Reply all
Reply to author
Forward
0 new messages