Гетерогенный выбор типов в HashMaps - PullRequest
0 голосов
/ 30 ноября 2018

Возможно ли иметь HashMap, который принимает унифицированный ключ (скажем, типа 'String'), но имеет значение, которое варьируется.Для примера рассмотрим HashMap m .Мне нужна следующая функциональность:

    m.get("UID1"); // This fetches a String value 
    m.get("UID2"); // This fetches another type like a class instance

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

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

Если вы хотите использовать Strings в качестве ключей, вы потеряете безопасность типов, и нет никакого способа обойти это.Вы просто будете отказываться от всей информации, имеющейся у компилятора, и будете вынуждены предоставить ее самостоятельно.

Вместо этого вы можете использовать некоторый класс-оболочку для String, который также содержит информацию о типе.Таким образом, вы можете получить разумную степень безопасности типов.

Вот пример для класса Foo, который оборачивает HashMap и предоставляет методы safe put и get типа:

public class Foo {

static class TypedKey<T> {
    final Class<T> clazz;
    final String id;
    public TypedKey(Class<T> clazz, String id) {
        this.clazz = clazz;
        this.id = id;
    }
    @Override
    public int hashCode() {
        return id.hashCode();
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof TypedKey)) {
            return false;
        }
        return id.equals(((TypedKey<?>) obj).id);
    }
    @Override
    public String toString() {
        return id;
    }
}

static final TypedKey<String> STRING_KEY = new TypedKey<>(String.class, "String");
static final TypedKey<Integer> INTEGER_KEY = new TypedKey<>(Integer.class, "Integer");

public static void main(String[] args) {
    Foo foo = new Foo();

    foo.put(STRING_KEY, "bar");
    String bar = foo.get(STRING_KEY);

    foo.put(INTEGER_KEY, 42);
    int baz = foo.get(INTEGER_KEY);

    foo.put(STRING_KEY, 42);
}

final Map<TypedKey<?>, Object> map = new HashMap<>();

public <T> void put(TypedKey<T> key, T value) {
    map.put(key, value);
}

@SuppressWarnings("unchecked")
public <T> T get(TypedKey<T> key) {
    return (T) map.get(key);
}

}
0 голосов
/ 01 декабря 2018

Рассмотрите возможность использования классов в качестве ключей, а не укусов.Это даст вам возможность сделать это безопасным для типов способом, описанным Джошуа Блохом как «типизированный безопасный гетерогенный контейнер»:

public static class Container {
  private Map<Class<?>, Object> store = new HashMap<>();

  public <T> void put(Class<T> type, T value) {
    store.put(Objects.requireNonNull(type), value);
  }

  public <T> T get(Class<T> type) {
    return type.cast(store.get(type));
  }
}

Вы можете поместить значение и получить его безопасным способом, например так:

Container container = new Container();

container.put(String.class, "test");
container.put(Integer.class, Integer.valueOf(5));

String s = container.get(String.class);
Integer i = container.get(Integer.class);

Но это будет работать, только если у вас есть только одно значение для типа.

0 голосов
/ 30 ноября 2018

Вы можете сделать что-то вроде этого:

HashMap<String, Object> m = new HashMap<>();

//Retreive a string:
String myString = (String) m.get("UID1");

//Retreive a variable of any type
MyType variable = (MyType) m.get("UID2");

Или, если возможно, вы можете установить тип вашего hashmap на нужный вам тип, и если вы хотите String, вы можете сделать toString ().

Например:

HashMap<String, MyObject> m = new HashMap<>();

//Retreive the string representation of your object:
String myString = m.get("UID1").toString();

//Retreive the object:
MyObject object = m.get("UID2");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...