2008-12-12 13 views
6

Si usa un EnumSet para almacenar valores binarios convencionales (1,2,4, etc.), cuando hay menos de 64 elementos, se me hace creer que esto se almacena como un bit vector y se representa de manera eficiente como un largo. ¿Hay una manera simple de obtener el valor de este tiempo? Quiero una forma rápida y sencilla de almacenar el contenido del conjunto en un archivo o base de datos.Obtener el valor de un EnumSet en Java

Si yo estaba haciendo esto a la antigua usanza, que acababa de usar mucho, y hacer el bit twidling a mí mismo, a pesar de todos los problemas de typesafety etc.

Respuesta

6

Por lo que yo sé, esto no está expuesto. Básicamente puede reescribirlo usted mismo, eche un vistazo al código de EnumSet para hacerse una idea del código, pero es una pena que no haya una manera más agradable de hacerlo :(

+1

Reflection dark magic se podría usar para recuperar el valor, aunque esto no sería ni "rápido" ni "simple". –

+0

EnumSet es en realidad abstracto, por lo que sería aún peor. –

1

EnumSet implementa Serializable, por lo que sólo podría escribirlo con un ObjectOutputStream.

5

No creo que esto . se puede hacer de una manera genérica en la conversión a una larga es bastante fácil:.

public static <T extends Enum<T>> long enumSetToLong(EnumSet<T> set) 
{ 
    long r = 0; 
    for(T value : set) 
    { 
     r |= 1L << value.ordinal(); 
    } 
    return r; 
} 

no sé cómo es posible que convertir de una larga vuelta a EnumSet genéricamente no hay manera (por debajo de reflexión) I saber para obtener en la matriz de valores de la enumeración para hacer la búsqueda. Tendría que hacerlo en un por-enum base

Creo que la serialización es el camino a seguir. Sólo de serie Al igual que un largo sería más susceptible a los errores de control de versiones, o errores causados ​​por la reorganización de las constantes en la enumeración.

+0

Debería verificar que los ordinales tengan menos de 64. long (+ Class) para EnumSet. Es posible que pueda obtener todos los valores de una enumeración. –

+0

++, pero realmente, no deberías estar usando ordinales. Configurar un sistema de indexación interno –

0

La implementación (típica, no obligatoria) de EnumSet usa los ordinales de valores enum. No debe suponer que los ordinales siempre serán los mismos. Por lo tanto, si desea almacenar conjuntos de enum de manera eficiente utilizando ordinales, también debe almacenar un mapa de enum name a ordinal (probablemente almacenado como una secuencia de nombres enum).

EnumSet en sí mismo no parece tener una gran forma serializada. Simplemente arroja una de enumeraciones. El cuerpo del cual se transcribirá en una serie de referencias de objetos enteros en lugar de un conjunto de bits.

0

BitSet puede ser útil en esta situación, ya que proporciona la transformación a/desde una matriz de bytes. Es posible que aún necesite declarar un enum con valores explícitos (1,2,3 ..) para BitSet indeces. A diferencia de long, que siempre es de 64 bits, BitSet no parece que permita restringir su longitud (a, por ejemplo, 64 bits).

2

Según lo mencionado por Jon Skeet, esta información no está expuesta. Pero Dave Ray mostró cómo calcularlo fácilmente. Hice una biblioteca que hace tales conversiones mucho más simples. También comprueba que realmente no hay más de 64 elementos si usa "largo". Tuve que crear un nuevo tipo de datos, pero se puede usar como un BitSet o un EnumSet. Tenga en cuenta que esto requiere Java 8 o posterior, ya que utiliza interfaces con implementaciones predeterminadas.

Aquí está el enlace: http://claude-martin.ch/enumbitset/

Ejemplo:

static enum MyEnum implements EnumBitSetHelper<MyEnum> { A, B, C } 
    public static void main(final String[] args) { 
    final EnumBitSet<MyEnum> set = EnumBitSet.of(MyEnum.A, MyEnum.C); 
    long bitmask = set.toLong(); // = 3 
    } 
1

si la adición de un parámetro con la clase de la enumeración que es posible.un ejemplo que convierte un enumset en un byte:

public static <T extends Enum<T>, U extends Enum<?>> byte toByte(EnumSet<T> set, Class<U> type) { 
    byte b = 0; 

    if(type.getEnumConstants().length > 8) { 
    throw new RuntimeException("enum set doesn't fit in one byte"); 
    } 

    for(Enum<?> e: type.getEnumConstants()) { 
    if(set.contains(e)) { 
     b |= 1 << e.ordinal(); 
    } 
    } 

    return b; 
} 

public static <E extends Enum<E>> EnumSet<E> toSet(byte b, Class<E> type) { 
    E[] enums = type.getEnumConstants(); 
    EnumSet<E> enumSet = EnumSet.noneOf(type); 

    for(int bit = 0; bit < 8; bit++) { 
    if((b & 1 << bit) > 0) { 
     enumSet.add(enums[bit]); 
    } 
    } 

    return enumSet; 
} 
Cuestiones relacionadas