如果使用EnumSet
存储常规二进制值(1,2,4等),那么当少于64个项目时,我会认为这是存储为位向量并且是有效地表示为长期。有没有一种简单的方法来获得这个长期的价值。我想要一种快速简单的方法将集合的内容存储在文件或数据库中。
如果我以旧方式这样做,我只会使用很长时间,尽管存在所有类型安全等问题,我还是会自己做点什么。
答案 0 :(得分:6)
据我所知,这并未曝光。您基本上可以自己重写它 - 看看EnumSet的代码以了解代码 - 但遗憾的是没有更好的方法来获取代码:(
答案 1 :(得分:5)
我不认为这可以通用方式完成。转换为long非常简单:
public static <T extends Enum<T>> long enumSetToLong(EnumSet<T> set)
{
long r = 0;
for(T value : set)
{
r |= 1L << value.ordinal();
}
return r;
}
我不知道你怎么可能从一个长回到一般的EnumSet。我知道没有办法(缺少反射)来获取枚举的values数组来进行查找。你必须在每个枚举的基础上这样做。
我认为序列化是要走的路。只需将序列化作为长整数就更容易受到版本错误的影响,或者重新排列枚举中的常量所导致的错误。
答案 2 :(得分:2)
如Jon Skeet所述,此信息未公开。但Dave Ray展示了如何轻松计算它。 我创建了一个库,使这种转换变得更加简单。如果使用&#34; long&#34;它还会检查实际上不超过64个元素。我不得不创建一个新的数据类型,但它可以像BitSet或EnumSet一样使用。请注意,这需要Java 8或更高版本,因为它使用具有默认实现的接口。
这里是链接:http://claude-martin.ch/enumbitset/
示例:
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
}
答案 3 :(得分:1)
EnumSet
实施Serializable
,因此您可以使用ObjectOutputStream
将其写出来。
答案 4 :(得分:1)
如果使用枚举类添加参数,则可以。将enumset转换为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;
}
答案 5 :(得分:0)
EnumSet的(典型 - 它没有强制要求)实现使用枚举值'序数。你不应该认为序数总是保持不变。因此,如果您想使用序数有效地存储枚举集,您还应该将枚举名称中的映射存储到序数(可能存储为枚举名称序列)。
EnumSet本身似乎没有很好的序列化形式。它只是抛弃了一个枚举。其主体将被转录为一系列整数对象引用而不是位集。
答案 6 :(得分:0)
BitSet
可能在这种情况下很有用,因为它提供了对字节数组的转换。您可能仍需要为enum
个indeces声明一个BitSet
的显式值(1,2,3 ..)。与long(总是64位)不同,BitSet
似乎不允许限制其长度(例如64位)。