从多个枚举类型为Map创建唯一键

时间:2015-06-25 09:55:50

标签: java dictionary enums multikey

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

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

以下是两个枚举的片段 -

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 

谢谢!

2 个答案:

答案 0 :(得分:0)

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

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个枚举。

答案 1 :(得分:0)

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

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构造函数中保持相同的参数顺序。