2015-11-28 2 views
1

Мне нужно использовать карту, в которой хранятся только ключи типа Integer, String и Long. Одно решение: для хранения типа объекта и проверки метода put с помощью оператора instanceof. Есть ли лучшее решение, возможно с перечислениемСохранение определенных типов данных в hashmap

+6

Можете ли вы дать некоторую предысторию, почему ты нуждаешься в этом? Похоже, вы должны пересмотреть свой дизайн. –

+0

У меня нет контроля над дизайном. Это просто требование, которое необходимо выполнить наилучшим образом. Я сделал это одним экземпляром оператора. Просто изучите, есть ли лучший способ – kakoli

ответ

1

Вы можете использовать карту и хранящий Long As String в нее

или вы можете использовать два различных HashMap и дублировать поместить/получить методы. Если у вас есть два типа, это, вероятно, для двух разных вещей, и наличие двух разных карт должно быть правильным ответом.

1

Создайте класс, который имеет карту в качестве члена, и добавьте методы, которые будут хранить и извлекать int и long как строки.

class MyMap { 
    private Map mabObject = Map<String, Object>; 

    public void add(long key, Object value) { 
     mapObject.put(Long.toString(key),value); 
    } 

    public void add(String key, Object value) { 
     mapObject.put(key, value); 
    } 

    public Object get(long key) { 
     return mapObject.get(Long.toString(key)); 
    } 

    public Object get(String key) { 
     return mapObject.get(key); 
    } 
} 
0

Я согласен с комментарием Павла Боддингтон, и необходимость такого трюка показывает, что код запахов.

Просто для забавного упражнения (не для производственного кода) Я привел пример, который показывает, что мы можем сделать во время компиляции для ограничения типов ключей на карте.

Например, мы можем создать оболочку, допускающую только значения определенных классов.

общая/карта/Wrap.java

package common.map; 

import java.util.Arrays; 
import java.util.List; 

public class Wrap<T> { 
    private T value; 

    private Wrap(T value){ 
    this.value = value; 
    } 

    public T get() { 
    return this.value; 
    } 

    /* 
    * it's important to implement this method 
    * if we intend to use Wrap instances as map's key 
    * 
    * and it's needed to see that hash codes are computing differently in different classes, 
    * and depending on `allowedClasses` contents we can face some unexpected collisions 
    * so if you care of performance - test your maps usage accurately 
    */ 
    public int hashCode() { 
    return this.value.hashCode(); 
    } 

    /* 
    * static 
    */ 

    private static List<Class> allowedClasses = Arrays.asList(Long.class, String.class); 

    public static <T> Wrap<T> create(Class<? extends T> clazz, T value) { 

    if (!allowedClasses.contains(clazz)) { 
     throw new IllegalArgumentException("Unexpected class " + clazz); 
    } 

    return new Wrap<>(value); 
    } 

    public static <T> Wrap<T> create(AllowedClasses allowedClass, T value) { 
    return create(allowedClass.clazz, value); 
    } 

    public enum AllowedClasses { 
    LONG(Long.class), 
    STRING(String.class); 

    private Class clazz; 

    AllowedClasses(Class clazz) { 
     this.clazz = clazz; 
    } 
    } 
} 

И давайте запустим его

общая/карта/Example.java

package common.map; 

import common.map.Wrap.AllowedClasses; 

import java.util.HashMap; 
import java.util.Map; 

public class Example { 

    public static void main(String... args) { 

    Map<Wrap, Object> map = new HashMap<>(); 

    // next two lines create wrappers for values of types we added to enum AllowedClasses 
    // but since enums cannot have type parameters, we are not able to check 
    // if the second parameter type is compatible with a type associated with given enum value 
    // so I think usage of enum is useless for your purpose 
    Wrap<?> valLong0 = Wrap.create(AllowedClasses.LONG, "the string in place of Long is OK"); 
    Wrap<?> valString0 = Wrap.create(AllowedClasses.STRING, 12345); 


    // from the next lines you can see how we can use the Wrap class to keep 
    // only allowed types to be associated with the map keys 

    Wrap<Long> valLong = Wrap.create(Long.class, 1L); // legal 
    Wrap<String> valString = Wrap.create(String.class, "abc"); // legal 

    Wrap<String> valWrong = Wrap.create(String.class, 123); // doesn't compile 

    Wrap<Object> valWrong2 = Wrap.create(Object.class, 123); // compiles but throws exception in runtime 

    Object obj = ThirdParty.getObjectOfUnknownClass(); 
    Wrap<?> valDynamic = Wrap.create(obj.getClass(), obj); // compiles but MAYBE throws exception in runtime 


    // so we get to this point only if all the wrappers are legal, 
    // and we can add them as keys to the map 

    map.put(valLong, new Object()); 
    map.put(valString, new Object()); 
    map.put(valDynamic, new Object()); 
    } 
} 
Смежные вопросы