具有一组有限键且每个键仅接受一种类型值的 Hashmap?

发布于 2024-11-19 08:54:59 字数 495 浏览 3 评论 0原文

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

为了提供更多背景信息,我的目标是构建一个 Tweener 实用程序,因为我在 Java 中发现没有这样的库,除了 SumoTween 之外,它根本不符合我的需求。我正在尝试像 Caurina 那样建立我的课程。如果您有更好的选择可以节省我的时间和麻烦,请随时分享(无论是关于 Tweeners 还是关于我的 Hashmap 问题)。顺便说一句,我正在做这个 Tweener,以便在我正在构建的 Android 游戏中使用它,以便在位图/可绘制对象上执行动画(据我所知,不能使用这些动画类)。

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

Ok, this might be a little hard to explain. I'm looking for a way to build a Hashmap of some sort, which will be populated with keys that I already know (because they are properties of the object I am creating). Each of these known keys will have values that are either a String, an int or float (which will be autoboxed), or - later - some kind of object/ function (I still don't know how I'll do that part, but it'll be further along the way anyway). I also want to set which type accepts each of the key (say key "x" will only accept an Integer type of value, key "equation" will only accept a string, etc.).

Just to give more context, my goal is to build a Tweener utility, as I found no such library in Java, except for SumoTween, that doesn't fit my needs at all. I'm kind of trying to build my classes the way Caurina is. If you have a better alternative that would save me time and trouble, please feel free to share (be it about Tweeners or about my Hashmap question). By the way, I'm doing this Tweener to use it in an Android game I'm building, in order to do animations on bitmap/drawable objects (can't use the animation classes for those afaik).

PS : This is my first question on this website, I hope I don't sound too confused; Please bear with me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

静谧 2024-11-26 08:54:59

为什么要使用哈希图呢?如果您知道“键”,只需与这些成员一起创建一个类,然后您可以根据需要键入它们。

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

Why are you using a hashmap for this? If you have known "keys", just make a class with those members and then you can type them however you want.

If you really must use a hashmap for some reason, you can just extend it and override the put() method to check for your magic values. But I strongly recommend against that, it's poor design.

木落 2024-11-26 08:54:59

如果我理解正确的话,你基本上是在寻找 HashMap。这是正确的吗?

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

If I understand you correctly, you are basically looking for a HashMap. Is that correct?

PS Yes, I know that using "Object" that way isn't very pretty.

起风了 2024-11-26 08:54:59

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

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

I'm not entirely sure if this is what you're asking for, but it sounds like you could use some kind of interface/abstract class for the key and implement/extend it appropriately for each key type, e.g.:

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

Then have something like:

HashMap<Key, Integer> map = new HashMap<Key, Integer>();
我的影子我的梦 2024-11-26 08:54:59

我想说创建一个继承自 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());
    }
}

I'd say create a custom class that inherits from say HashMap, on insert you check the specified key/value if it's valid.

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());
    }
}
甜是你 2024-11-26 08:54:59

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

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

You could have separate maps, one for the Strings; another for the Integers, etc. And when adding to any of these maps, you could add the key to a (global) set, to ensure that no key is duplicated across maps. I suspect that wouldn't meet your needs very well (and of course the lookup is a little more involved), but if it works for you, great.

Maybe a better option is to add another level of indirection. Make your map a Hashmap where YourThing has subclasses for each of the types you want to hold. So, a StringYourThing has a String data member; an IntegerYourThing has an int data member, etc. I wouldn't be surprised to find that YourThing starts to take on functionality that is currently a switch statement somewhere inside another class that is trying to deal consistently with all these different data types. If that class could simply interact with a YourThing, it could get simpler. But it's hard to know without seeing your code.

淡淡離愁欲言轉身 2024-11-26 08:54:59

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

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

我觉得大致是这样的:

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 起点。

I would rather avoid using map directly. What you are looking for is probably something more application specific:

Assume the whole thing you are building is for bunch of settings. Your "Setting" will have a predefined set of key. Each key is predefined to accept corresponding setting value of specific value. If incorrect type is provided, exception will be thrown.

I think something roughly like this is reasonable:

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

There are lots of place that can be improved according to your usage:
if ur types are very dynamic, u may make SettingValueType something like a bunch of strategies, or use Class directly. setSetting() can made generic and take Class as extra parameter etc. But at least, this should give u a starting point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文