Might EnumMap be considered a reasonable alternative to Java beans?
Asked Answered
K

5

2

Curious if anybody has considered using EnumMap in place of Java beans, particularly "value objects" (with no behavior)? To me it seems that one advantage would be that the name of a "property" would be directly accessible from the backing Enum, with no need for reflection, and therefore I'd assume it would be faster.

Kinesiology answered 31/8, 2009 at 20:2 Comment(5)
Maybe I am showing my ignorance related to java beans (I only use them in relationship to persistence applications) however I would assume that these are different problems - iirc the enum map is designed to be optimized for enum lookups while java beans are designed to transfer data information across the wire - or am I completely off base or missing something critical here?Goldberg
What is the advantage of using EnumMap compared to plain immutable classes?Detrain
You are assuming that all your variables are of the same type. Even so, I don't think you'd see much in the way of additional clarity of code(!). (BTW: We've called "Value Objects" Data Transfer Objects for the last eightish years.)Limy
Its not just that an EnumMap is optimized, but also that the keys are restricted to values from the backing Enum. EnumMaps as opposed to immutable "value object" classes offer the advantage of decreased boilerplate, verbosity and "class proliferation". Case in point, sometimes you want property names, for instance when mapping data from a ResultSet, and you either have to use reflection, or in addition to all the boilerplate getters/setters, additional static final Strings equating to the property names.Kinesiology
@Tom: there is, or should be, difference between Value Objects and Data Transfer Objects. And that is, that the latter should define a data transfer strategy. But good point about "assuming all your variables are of the same type"; in my case they all are, Strings. So that is definitely a necessary restriction when relying on EnumMap instead. Wish these were answers instead of comments though.Kinesiology
A
1

It may be a little faster then using reflection (I didn't measure it, didn't find any metrics in Google either); however there are big disadvantages to this approach:

  1. You're losing type safety. Instead of int getAge() and String getName() everything is Object get(MyEnum.FIELD_NAME). That'll provide for some ugly code and run-time errors right there.

  2. All the javabean niceties we've come to love and enjoy (for example, property-level annotations) are gone.

  3. Since you can have NO BEHAVIOR AT ALL, the applicability of this approach seems rather limited.

The bottom line is - if you really truly need that alleged :-) boost in performance (which you'll have to measure to prove it exists) this may be a viable approach under very specific circumstances. Is it a viable alternative to javabeans at large? Most certainly not.

Admissible answered 31/8, 2009 at 20:35 Comment(2)
if you have generics, enumMap's get() method returns the correct type.Crowell
It still will only return a single type for all keys.Oberstone
S
1

A bean is meant to be mutable, hence the setter methods. EnumMap is comparable in speed to using a HashMap with integers as the Key, but are Keys are Immutable. Beans and EnumMaps serve two different purposes. If all of the Keys are known at design time and are guaranteed to never change, then using an EnumMap will be fine.
Updating a bean is much simpler than changing the backing Enum of the EnumMap with much less chance of creating errors downstream in the code.

Swarts answered 31/8, 2009 at 20:31 Comment(2)
I don't think that's what OP meant. Instead of setAge() bean setter you'd call myMap.put(MyFieldNames.AGE, age). EnumMap is very "mutable" in that sense.Admissible
I'll clarify my point. The fact that EnumMap keys are immutable is irrelevant - OP compares them to property (and, ergo, method) names which are "immutable" by definition, just like they are "known at design time". Both method names and EnumMap keys may change; if they do you'll have to change code in both cases. Updating a bean is not simpler then adding another field to enum; errors in dependent code will be triggered either way (e.g. wrong method name or undefined symbol for missing enum constant). The biggest difference (and the biggest problem in EnumMap approach) is type safety.Admissible
A
1

It may be a little faster then using reflection (I didn't measure it, didn't find any metrics in Google either); however there are big disadvantages to this approach:

  1. You're losing type safety. Instead of int getAge() and String getName() everything is Object get(MyEnum.FIELD_NAME). That'll provide for some ugly code and run-time errors right there.

  2. All the javabean niceties we've come to love and enjoy (for example, property-level annotations) are gone.

  3. Since you can have NO BEHAVIOR AT ALL, the applicability of this approach seems rather limited.

The bottom line is - if you really truly need that alleged :-) boost in performance (which you'll have to measure to prove it exists) this may be a viable approach under very specific circumstances. Is it a viable alternative to javabeans at large? Most certainly not.

Admissible answered 31/8, 2009 at 20:35 Comment(2)
if you have generics, enumMap's get() method returns the correct type.Crowell
It still will only return a single type for all keys.Oberstone
S
1

I wrote a Record class that maps keys to values and works by delegating to a fully synchronized EnumMap. The idea is that a Record can get new fields at runtime whereas the Bean can't. My conclusion is that with this flexibility comes a performance hit. Here's a run comparing the Record class to a fully synchronized Bean. For 10 million operations:

Record  set(Thing, a)  458 ms
Bean    setThing(a)    278 ms
Record  get(Thing)     398 ms
Bean    getThing       248 ms

So, there is something to gain in knowing your data objects and writing a class that models them statically. If you want to have new fields padded on to your data at runtime, it will cost you.

Surety answered 20/2, 2010 at 17:52 Comment(0)
K
0

I had not previously specified this, but I am working with a ResultSet. Therefore I want to provide this answer for the sake of completeness.

Commons/BeanUtil's "RowSetDynaClass" could be the happy medium between the excessive boilerplate associated with concrete beans, and the limitations of EnumMap

Kinesiology answered 1/9, 2009 at 11:24 Comment(0)
A
0

I don't understand how you can remove 'class profileration' with EnumMaps. Unless you have a generic enum with 20-odd properties to reuse for every 'bean', you're still inventing an enum to use for each enum map, e.g.

public enum PersonDTOEnum {
     A, S, L;
}

as opposed to

class Person {

    int a;
    int s;
    String l;

    // getters + setters elided
}

Not to mention that everything is a String now.

Astoria answered 1/9, 2009 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.