1

好的,这可能有点难以解释。我正在寻找一种方法来构建某种 Hashmap,它将填充我已经知道的键(因为它们是我正在创建的对象的属性)。这些已知键中的每一个都将具有字符串、int 或浮点值(将被自动装箱),或者 - 稍后 - 某种对象/函数(我仍然不知道我将如何做那部分,但无论如何它会更进一步)。我还想设置哪个类型接受每个键(比如键“x”只接受整数类型的值,键“方程式”只接受字符串等)。

只是为了提供更多上下文,我的目标是构建一个 Tweener 实用程序,因为我在 Java 中没有找到这样的库,除了 SumoTween,它根本不符合我的需求。我有点想像 Caurina 那样建立我的课程。如果您有更好的替代方案可以节省我的时间和麻烦,请随时分享(无论是关于 Tweeners 还是关于我的 Hashmap 问题)。顺便说一句,我正在做这个 Tweener 以在我正在构建的 Android 游戏中使用它,以便在位图/可绘制对象上制作动画(不能为那些 afaik 使用动画类)。

PS:这是我在这个网站上的第一个问题,我希望我听起来不会太困惑;请多多包涵。

4

6 回答 6

4

你为什么要为此使用哈希图?如果您知道“密钥”,只需使用这些成员创建一个类,然后您可以随意键入它们。

如果您出于某种原因确实必须使用哈希图,您可以扩展它并覆盖 put() 方法来检查您的魔法值。但我强烈建议不要这样做,这是糟糕的设计。

于 2011-07-10T23:44:37.730 回答
0

如果我理解正确,您基本上是在寻找 HashMap。那是对的吗?

PS 是的,我知道以这种方式使用“对象”不是很漂亮。

于 2011-07-10T23:44:22.597 回答
0

我不完全确定这是否是您所要求的,但听起来您可以为密钥使用某种接口/抽象类并为每种密钥类型适当地实现/扩展它,例如:

public interface Key {}

private static final class StringKey implements Key {
    private final String value;

    public StringKey(String value) {
        this.value = value;
    }

    // hashCode, equals here
}

// IntegerKey, FloatKey, etc similarly

然后有类似的东西:

HashMap<Key, Integer> map = new HashMap<Key, Integer>();
于 2011-07-10T23:44:38.180 回答
0

我会说创建一个继承自 HashMap 的自定义类,在插入时检查指定的键/值是否有效。

public static final HashMap<String, Class<?>> allowedTypes = new HashMap<String, Class<?>>() {{
    put("key1", String.class);
    put("key2", Integer.class);
    // etc
}};

public class CustomHashMap extends HashMap {
    public Object put(Object key, Object value) {
        Class<?> type = allowedTypes(key);

        if(type != null && !type.isInstance(value))
            throw new IllegalArgumentException("Invalid type for key " + key);

        return put(key, value);
    }

    private void PutAll(Map m) {
        for(Entry<?, ?> entry : m.entrySet())
            put(entry.getKey(), entry.getValue());
    }
}
于 2011-07-10T23:45:02.847 回答
0

你可以有单独的地图,一个用于字符串;另一个用于整数等。当添加到这些映射中的任何一个时,您可以将键添加到(全局)集合中,以确保映射之间没有重复键。我怀疑这不能很好地满足您的需求(当然查找会涉及更多),但如果它适合您,那就太好了。

也许更好的选择是添加另一个级别的间接性。将您的地图设为 Hashmap,其中 YourThing 为您想要保存的每种类型提供子类。所以,StringYourThing 有一个 String 数据成员;IntegerYourThing 有一个 int 数据成员等。我不会惊讶地发现 YourThing 开始承担当前是另一个类中某个地方的 switch 语句的功能,该类试图一致地处理所有这些不同的数据类型。如果该类可以简单地与 YourThing 交互,它会变得更简单。但是如果没有看到你的代码就很难知道。

于 2011-07-10T23:55:45.077 回答
0

我宁愿避免直接使用地图。您正在寻找的可能是更特定于应用程序的东西:

假设你正在构建的整个东西都是为了一堆设置。您的“设置”将有一组预定义的键。每个键都预先定义为接受特定值的相应设置值。如果提供了不正确的类型,将会抛出异常。

我认为大致这样的事情是合理的:

enum SettingValueType {
  public boolean isCorrectType(Object obj) {
    return true if obj is correct type represented by this enum 
  }
  STRING, INT, FLOAT   // add support to other type if u want
};

clsss SettingValue {
  SettingValueType type;
  Object value;
}

class SettingRepo {  // a repository of setting entries
  private Map<String, SettingValueType> allowedKeyAndType;
  private Map<String, Object> settings;

  SettingRepo() {
    // setup allowedKeyAndType programmatically or from config etc, depends on your design
  }

  public SettingValue setSetting(String key, Object value)  {

    SettingValueType valueType = allowedKeyAndType.get(key);
    if (valueType == null) {
      throw new KeyNotAllowedException();
    }

    if (v!alueType.isCorrectType(value) {
      throw new ValueIncorectTypeException();
    }

    return settings.put(key, new SettingValue(valueType, value));
    }
  } 

  public SettingValue getSetting(String key) {
    // u may throw exception if key is not in predefined set

    return settings.get(key);
  }

  // u may consider adding some convinient methods too:
  public String setStringSetting(String key, String value) {
    if alllowedKeyAndType do not contains key {
      throw KeyNOtAllowedException
    }
    if type is not STRING {
      throw IncorrectTypeExceptin
    }
    settings.put(key, new SettingValue(STRING, value))
  }

  public String getStringSetting(String key) {
    // should be straight forward now, right?
  }    
}

有很多地方可以根据您的使用情况进行改进:如果您的类型非常动态,您可以将 SettingValueType 设置为一堆策略,或者直接使用 Class。setSetting() 可以通用化并将 Class 作为额外参数等。但至少,这应该给 ua 起点。

于 2011-07-11T01:06:28.757 回答