File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Enums (Is this the best way)? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of JavaScript Promises Essentials this week in the JavaScript forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Enums (Is this the best way)?" Watch "Enums (Is this the best way)?" New topic
Author

Enums (Is this the best way)?

Tom Sullivan
Ranch Hand

Joined: Dec 20, 2005
Posts: 72
I am still pretty new to Java and programming in general. But, it is getting to be much more fun lately. What's with the desire to work longer hours when you code? Let me give a little background on my question.

After creating a whole slew of methods to check several arrays against each other and themselves in order to make sure that they don't have dups, I came across HashSet<>. What was all those lines of code became:



HashSet won't allow dups so there is no need for all this code. Then I came across the Enum class. I am embarrassed to say that it took some time to figure out and I am still not totally sure that I have it. Here is what I am trying to do:

I want to receive a string and be able to tell if it is some type. The string is a formatted message from a socket. So, I am in process of creating an enum like this:



Before I go running down the wrong track again, does what I am doing with the enum make sense? In particular, is there an easier way to get the string value that matches the enum than to build a switch statement like I am doing?

[ March 02, 2006: Message edited by: Tom Sullivan ]
[ March 02, 2006: Message edited by: Tom Sullivan ]
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
It looks to me like an enum is appropriate for your application. That is to say, the question "do you have a finite set of values to logically group?" is answered "yes" by you. So you list your values in a group:

This appears to be what you have done, however, you have convoluted your enum with a type mapping. Granted, enums tempt you to do this, and even more so, it is becoming a de facto way of doing things (albeit incorrect). In the above code sample, you merely specify your finite values that belong to your group. There is a logical distinction between these values and what they might map to (or what might map to them). To express a String mapping, you should define your own contract:

Then you can write your implementation that is backed by a java.util.Map (or EnumMap if you insist on some orthodoxy). This is a cleaner separation of concerns, and is much more flexible as new requirements emerge, since you have accurately expressed your existing requirement with better level of atomicity (allowing the new requirements to merge with the existing software i.e. appropriate symbiotism.

Good luck.


Tony Morris
Java Q&A (FAQ, Trivia)
Tom Sullivan
Ranch Hand

Joined: Dec 20, 2005
Posts: 72
Thank you for that, Tony. Just to make sure that I have it, I should create an interface which is implemented by any class which reports the mappings. Then when the matching of enums to strings changes, it won't affect my implementation of the enum types (they will automatically be changed to the new implementation). Right?

So, does the following make sense:



Thank you for the input. I want to make sure I got it so if the above is off-base, please let me know.
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
Originally posted by Tom Sullivan:
Thank you for that, Tony. Just to make sure that I have it, I should create an interface which is implemented by any class which reports the mappings. Then when the matching of enums to strings changes, it won't affect my implementation of the enum types (they will automatically be changed to the new implementation). Right?

So, does the following make sense:



Thank you for the input. I want to make sure I got it so if the above is off-base, please let me know.


Not quite.

Hope this helps.
Tom Sullivan
Ranch Hand

Joined: Dec 20, 2005
Posts: 72
I got it now.

That makes a lot of sense.
Tom Sullivan
Ranch Hand

Joined: Dec 20, 2005
Posts: 72
Just to follow up, I created an interface and EnumMap in the interfaceImp. To get values, I no longer have 50 lines of switch statements and instead have:



Nothing is hard coded now where the enums are concerned. I use a DOM to map the values to the enum. The DOM is created from an XML doc which can be modified by anyone (who should modify it) at any time outside of the software. Now I can restrict the rest of my design to using the enums and never have to worry about what happens if an enum map changes. Pretty cool. Thanks so much for the input.
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
The problem with your solution is that you now have O(n) seek, and O(1) is optimal - this is the whole purpose of EnumMap (and Map). You should not be iterating the Map, merely performing a "get" operation with a given key.

The good thing is that if you have since progressed, and even written your unit tests (requirements) appropriately, you should be able to alter your implementation without having any adverse side-effect.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Tony Morris:
The problem with your solution is that you now have O(n) seek, and O(1) is optimal


That is only a problem for big n's.

In fact, for small values of n, it is in general quite possible that an O(n) algorithm actually is faster than an O(1) algorithm (although I doubt it in this case).

Which doesn't mean that I wouldn't use a Map in this case - it would probably be the more elegant solution, *if* you don't have to duplicate knowledge for that.

Another solution to think about might be a Visitor.


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
"for big n where n > 2", which it is, otherwise, why use a for loop? If n were 1, then a single statement is sufficient; if n were 2, an if/else will do.

More importantly, I am explicitly avoiding the issue of failure of abstraction, and excessive specification of requirement in the local context, simply because of the verbose dialogue that will likely follow and I wish to avoid (call me lazy ).
Tom Sullivan
Ranch Hand

Joined: Dec 20, 2005
Posts: 72
Lazy or not, you have made me think and learn. I have gotten a lot out of the comments (despite what it may look like ).


The problem with your solution is that you now have O(n) seek, and O(1) is optimal - this is the whole purpose of EnumMap (and Map).


I need the enums so that I can do things like:

Processable p = new ProcessInstructions().doWork(MessageType.TYPE);

To get the value associated with a MessageType is easy and is the requirement of most of my design:

String value = map.get(MessageType.TYPE);

But, I am getting strings formatted like:

_client_controller | value (not Key) of MesageType |...

It is for these cases that I want the opposite of above:

MessageType m = map.get(String value);//which is why I have a for loop


You should not be iterating the Map, merely performing a "get" operation with a given key.


I have to work backwards from the string when I get messages from the socket so that I can set the type where other threads pick up and do what they need to do. For these cases, does it still make sense to implement a O(1) seek?
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Tony Morris:
"for big n where n > 2


Nope - the "big O" notation is an asymptotic notation - it only makes a statement about "big n", without specifying what "big" exactly means.

For example you could have

f(n)=1000
g(n)=0.5 * n

In which case the f solution would be slower for all n < 2000, although f is in O(1) and g is in O(n).

Mind you, this is only an example, showing that "big O" performance isn't a good argument in general (setting aside the fact that *performance* itself is a bad argument in general).

There are other, better reasons why I might use a Map in this specific case.
[ March 05, 2006: Message edited by: Ilja Preuss ]
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Tom, I'm not yet using Java 5, but with the Typesafe Enum pattern I often do the following:



I guess Tony won't like it, but I find it to be workig very well. It shouldn't be too hard to translate it to Java 5 enums...
Tom Sullivan
Ranch Hand

Joined: Dec 20, 2005
Posts: 72
LOL Ilja. That is how I started my design. But, from an abstraction point of view, what I have seems about as abstract as it gets. You can now pass me any value and I will tell you what enum type matches to the value (or null if no match which will be supported with an exception response next). The type and values are mapped outside of the software so you can just implement to the type and never have to worry about what is sent in as far as values go. The software does not even know what the values are until it reads the XML which happens when it builds the map.

Tony mentioned abstraction (or failure of it) in his last post. Thanks to Tony, the values can still change at any time and, as long as a reference to them in the XML is maintained, the software will work as expected. What I am trying to understand is, how is implementing a loop matching concrete keys to abstract values a failure of abstraction if it is.

This has been the most helpful personal discussion I have ever had here. Sincerely, thank you both for your input. I have learned a lot from it.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Tom Sullivan:
The software does not even know what the values are until it reads the XML which happens when it builds the map.


That is a very good approach when the values change often. If they don't, I'd think it's unnecessary complexity. So I'd say both approaches have their area of application.

Regarding your last question, I'd be interested in knowing, too. History shows that I often have problems following Tony's train of thought, though...
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Enums (Is this the best way)?