2015-06-25 6 views
1

У меня есть требование, когда несколько перечислений должны будут найти значение в i.e Map<Key,Value> (комбинация перечислений вернет уникальное значение). Я думаю, что есть много вариантов, таких как наличие обертки Object say Key, который будет действовать как ключ. Кроме того, мы можем использовать таблицу Guava, если ключи ограничены двумя (не уверены).Создайте уникальный ключ для Map из нескольких типов Enum

Хотел проверить ниже подход, при котором два перечислений сопоставляются с уникальным вычисленным значением, необходимы предложения для понимания -
я) Если этот подход отлично?
ii) Если да, то он масштабируемый? то есть она может быть легко родовое поддерживать «п» перечислений как в 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 

Спасибо!

+0

Вы хотите, чтобы ваш ключ состоял из нескольких значений enum * types * или нескольких значений enum * (одного и того же типа)? – Buurman

ответ

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; 
} 

Он должен быть достаточно устойчив к столкновениям из-за простого числа, и это расширяемый для поддержки п перечислений.

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" 

Обратите внимание, что он может объединить не перечисления, но любые типы с правильно определенными hashCode и equals. Однако вы должны поддерживать тот же порядок аргументов в конструкторе MultiKey.

+0

Спасибо за ответ - его удобная многокитайская реализация. – prash