在hashmap中存储特定数据类型

时间:2015-11-28 14:23:31

标签: java

我必须使用一个存储Integer,String和Long类型的键的映射。 一种解决方案:存储类型Object,并使用instanceof运算符进行put方法检查。有没有更好的解决方案,可能有enum

3 个答案:

答案 0 :(得分:1)

您可以使用地图并将Long存储为字符串

或者您可以使用两种不同的hashmap和重复的put / get方法。如果你有两种类型,它可能是两个不同的东西,有两个不同的地图应该是正确的答案

答案 1 :(得分:1)

创建一个将地图作为成员的类,并添加将存储和检索int的方法以及作为字符串的长整数。

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

答案 2 :(得分:0)

我同意Paul Boddington的评论,并且需要这样的技巧表明代码闻起来。

只是为了一个有趣的练习(不是生产代码)我已经做了一个例子,展示了我们在编译时可以做些什么来限制地图中的键类型。

例如,我们可以创建一个只允许特定类值的包装器。

<强>公共/图/ 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());
  }
}