代码之家  ›  专栏  ›  技术社区  ›  Miles D

Java中枚举集的取值

  •  6
  • Miles D  · 技术社区  · 16 年前

    如果你使用 EnumSet 为了存储传统的二进制值(1、2、4等),当少于64个项时,我会认为这是作为位向量存储的,并有效地表示为长。有没有一个简单的方法可以得到这个长的值?我想要一种快速而简单的方法来将集合的内容存储在文件或数据库中。

    如果我按老办法做的话,我只会用很长的时间,尽管有字体安全等问题,但我还是会自己做一些小动作。

    7 回复  |  直到 10 年前
        1
  •  6
  •   Jon Skeet    16 年前

    据我所知,这并没有暴露出来。你基本上可以自己重写它-看看Enumset的代码以了解代码-但遗憾的是,没有更好的方法来理解它:(

        2
  •  5
  •   Dave Ray    16 年前

    我认为这不能用一般的方法来完成。转换为长型非常容易:

    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。我不可能(除了反射)找到枚举的值数组来进行查找。你必须在每个枚举的基础上进行。

    我认为串行化是一种方法。只要序列化为long,就更容易受到版本控制错误或重新排列枚举中常量所导致的错误的影响。

        3
  •  2
  •   Claude Martin    11 年前

    如jon skeet所述,此信息不公开。但戴夫·雷演示了如何轻松计算。 我做了一个库,使这种转换变得简单多了。它还检查如果使用“long”,实际上不超过64个元素。我必须创建一个新的数据类型,但它可以像位集或枚举集那样使用。注意,这需要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
      }
    
        4
  •  1
  •   Michael Myers KitsuneYMG    16 年前

    EnumSet 器具 Serializable ,这样你就可以用 ObjectOutputStream .

        5
  •  1
  •   Christian    10 年前

    如果使用枚举类添加参数,则可以。将枚举集转换为字节的示例:

    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;
    }
    
        6
  •  0
  •   Tom Hawtin - tackline    16 年前

    Enumset的(典型的-它不是强制的)实现使用枚举值的序号。你不应该假定序数总是保持不变。因此,如果希望使用序数高效地存储枚举集,还应该存储从枚举名到序数的映射(可能存储为枚举名序列)。

    Enumset本身似乎没有很好的序列化形式。它只是从一个枚举中转储。其主体将被转录成一系列整数对象引用,而不是位集。

        7
  •  0
  •   Alex Kevin Panko    11 年前

    BitSet 在这种情况下可能很有用,因为它提供到字节数组/从字节数组的转换。您可能仍然需要声明 enum 具有显式值(1、2、3….) 位集合 优柔寡断不像long,它总是64位的, 位集合 似乎不允许限制其长度(例如64位)。