【问题标题】:Create a unique key for Map from multiple Enum types从多个 Enum 类型为 Map 创建唯一键
【发布时间】:2015-06-25 09:55:50
【问题描述】:

我有一个要求,即多个枚举需要在 Map<Key,Value> 中找到一个值(枚举的组合将返回一个唯一值)。 我认为有很多选择,比如有一个包装器对象说键,它将充当键。此外,如果键限制为两个(不确定),我们可以使用 Guava Table。

想要检查以下方法,其中两个枚举将映射到唯一的计算值,需要理解建议 -
i)如果这种方法很好?
ii) 如果是,它是否可扩展?即可以很容易地使其通用以支持'n'枚举 如toKey(Enum ...enums)

下面是两个枚举的 sn-p -

static Integer toKey(Status s, SubStatus ss) {
   return Integer.valueOf(s.ordinal() * SubStatus.values().length + ss.ordinal());
}

Status { NONE, PASS, WARN, REJECT }
SubStatus { NONE, SOFT_REJECT, HARD_REJECT }

Integer key1 = toKey(Status.REJECT, SubStatus.HARD_REJECT)
Integer key2 = toKey(Status.WARN, SubStatus.NONE)

then key1 != key2 

谢谢!

【问题讨论】:

  • 您希望您的密钥由(来自)多个枚举类型或多个枚举(相同类型)的(值)组成吗?跨度>

标签: java dictionary enums multikey


【解决方案1】:

您可以尝试使用此代码生成用作密钥的哈希码:

static int toKey(Status s, SubStatus ss) {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((s == null) ? 0 : s.hashCode());
  result = prime * result + ((ss == null) ? 0 : ss.hashCode());
  return result;
}

由于素数,它应该对碰撞相当稳健,并且可以扩展以支持 n 个枚举。

【讨论】:

    【解决方案2】:

    如果你想要一个通用的解决方案,你可以像这样引入一个数组包装器:

    import java.util.Arrays;
    import java.util.Objects;
    
    public final class MultiKey {
        private final Object[] elements;
    
        public MultiKey(Object... elements) {
            this.elements = Objects.requireNonNull(elements);
        }
    
        @Override
        public int hashCode() {
            return Arrays.hashCode(elements);
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null || getClass() != obj.getClass())
                return false;
            return Arrays.equals(elements, ((MultiKey) obj).elements);
        }
    
        @Override
        public String toString() {
            return Arrays.toString(elements);
        }
    }
    

    可以作为HashMap键使用:

    Map<MultiKey, String> testMap = new HashMap<>();
    testMap.put(new MultiKey(Status.NONE), "none");
    testMap.put(new MultiKey(Status.REJECT, SubStatus.SOFT_REJECT), "soft-reject");
    testMap.put(new MultiKey(Status.WARN, SubStatus.SOFT_REJECT), "warn");
    System.out.println(
        testMap.get(new MultiKey(Status.REJECT, SubStatus.SOFT_REJECT))); // prints "soft-reject"
    

    请注意,它不能组合枚举,而是任何具有正确定义的hashCodeequals 的类型。但是,您应该在 MultiKey 构造函数中保持相同的参数顺序。

    【讨论】:

    • 感谢您的回答 - 它是一个方便的多键实现。
    猜你喜欢
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    相关资源
    最近更新 更多