简体   繁体   English

优化枚举查找图

[英]Optimize Enum Lookup Map

I am wondering if there is a better way to create and search through the static Maps below. 我想知道是否有更好的方法来创建和搜索下面的静态地图。 As seen in the main() method. main()方法所示。

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public enum PokemonType {
  BUG("Bug"),
  DARK("Dark"),
  DRAGON("Dragon"),
  ELECTRIC("Electric"),
  FAIRY("Fairy"),
  FIGHTING("Fighting"),
  FIRE("Fire"),
  FLYING("Flying"),
  GHOST("Ghost"),
  GRASS("Grass"),
  GROUND("Ground"),
  ICE("Ice"),
  NORMAL("Normal"),
  POISON("Poison"),
  PSYCHIC("Psychic"),
  ROCK("Rock"),
  STEEL("Steel"),
  WATER("Water");

  private String name;

  @SuppressWarnings("serial")
  public static Map<PokemonType, Set<PokemonType>> noEffect = new HashMap<PokemonType, Set<PokemonType>>() {{
    put(BUG, new HashSet<PokemonType>());
    put(DARK, new HashSet<PokemonType>());
    put(DRAGON, new HashSet<PokemonType>());
    put(ELECTRIC, new HashSet<PokemonType>() {{ addAll(Arrays.asList(GROUND)); }});
    put(FAIRY, new HashSet<PokemonType>());
    put(FIGHTING, new HashSet<PokemonType>() {{ addAll(Arrays.asList(GHOST)); }});
    put(FIRE, new HashSet<PokemonType>());
    put(FLYING, new HashSet<PokemonType>());
    put(GHOST, new HashSet<PokemonType>() {{ addAll(Arrays.asList(NORMAL)); }});
    put(GRASS, new HashSet<PokemonType>());
    put(GROUND, new HashSet<PokemonType>() {{ addAll(Arrays.asList(FLYING)); }});
    put(ICE, new HashSet<PokemonType>());
    put(NORMAL, new HashSet<PokemonType>() {{ addAll(Arrays.asList(GHOST)); }});
    put(POISON, new HashSet<PokemonType>());
    put(PSYCHIC, new HashSet<PokemonType>());
    put(ROCK, new HashSet<PokemonType>());
    put(STEEL, new HashSet<PokemonType>());
    put(WATER, new HashSet<PokemonType>());
  }};

  @SuppressWarnings("serial")
  public static Map<PokemonType, Set<PokemonType>> notVeryEffective = new HashMap<PokemonType, Set<PokemonType>>() {{
    put(BUG, new HashSet<PokemonType>() {{ addAll(Arrays.asList(FIGHTING,FIRE,FLYING,GHOST,POISON,STEEL)); }});
    put(DARK, new HashSet<PokemonType>() {{ addAll(Arrays.asList(DARK,FIGHTING,STEEL)); }});
    put(DRAGON, new HashSet<PokemonType>() {{ addAll(Arrays.asList(STEEL)); }});
    put(ELECTRIC, new HashSet<PokemonType>() {{ addAll(Arrays.asList(DRAGON,ELECTRIC)); }});
    put(FAIRY, new HashSet<PokemonType>());
    put(FIGHTING, new HashSet<PokemonType>() {{ addAll(Arrays.asList(BUG,FLYING,POISON,PSYCHIC)); }});
    put(FIRE, new HashSet<PokemonType>() {{ addAll(Arrays.asList(DRAGON,FIRE,ROCK,WATER)); }});
    put(FLYING, new HashSet<PokemonType>() {{ addAll(Arrays.asList(ROCK,STEEL)); }});
    put(GHOST, new HashSet<PokemonType>() {{ addAll(Arrays.asList(STEEL)); }});
    put(GRASS, new HashSet<PokemonType>() {{ addAll(Arrays.asList(BUG,DRAGON,FIRE,FLYING,GRASS,POISON,STEEL)); }});
    put(GROUND, new HashSet<PokemonType>() {{ addAll(Arrays.asList(BUG,GRASS)); }});
    put(ICE, new HashSet<PokemonType>() {{ addAll(Arrays.asList(FIRE,ICE,STEEL,WATER)); }});
    put(NORMAL, new HashSet<PokemonType>() {{ addAll(Arrays.asList(ROCK,STEEL)); }});
    put(POISON, new HashSet<PokemonType>() {{ addAll(Arrays.asList(GHOST,GROUND,POISON,ROCK)); }});
    put(PSYCHIC, new HashSet<PokemonType>() {{ addAll(Arrays.asList(PSYCHIC,STEEL)); }});
    put(ROCK, new HashSet<PokemonType>() {{ addAll(Arrays.asList(FIGHTING,GROUND,STEEL)); }});
    put(STEEL, new HashSet<PokemonType>() {{ addAll(Arrays.asList(ELECTRIC,FIRE,STEEL,WATER)); }});
    put(WATER, new HashSet<PokemonType>() {{ addAll(Arrays.asList(DRAGON,GRASS,WATER)); }});
  }};

  @SuppressWarnings("serial")
  public static Map<PokemonType, Set<PokemonType>> superEffective = new HashMap<PokemonType, Set<PokemonType>>() {{
    put(BUG, new HashSet<PokemonType>() {{ addAll(Arrays.asList(DARK,GRASS,PSYCHIC)); }});
    put(DARK, new HashSet<PokemonType>() {{ addAll(Arrays.asList(GHOST,PSYCHIC)); }});
    put(DRAGON, new HashSet<PokemonType>() {{ addAll(Arrays.asList(DRAGON)); }});
    put(ELECTRIC, new HashSet<PokemonType>() {{ addAll(Arrays.asList(FIRE,WATER)); }});
    put(FAIRY, new HashSet<PokemonType>());
    put(FIGHTING, new HashSet<PokemonType>() {{ addAll(Arrays.asList(DARK,ICE,NORMAL,ROCK,STEEL)); }});
    put(FIRE, new HashSet<PokemonType>() {{ addAll(Arrays.asList(BUG,GRASS,ICE,STEEL)); }});
    put(FLYING, new HashSet<PokemonType>() {{ addAll(Arrays.asList(BUG,FIGHTING,GRASS)); }});
    put(GHOST, new HashSet<PokemonType>() {{ addAll(Arrays.asList(GHOST,PSYCHIC)); }});
    put(GRASS, new HashSet<PokemonType>() {{ addAll(Arrays.asList(GROUND,ROCK,WATER)); }});
    put(GROUND, new HashSet<PokemonType>() {{ addAll(Arrays.asList(ELECTRIC,FIRE,POISON,ROCK,STEEL)); }});
    put(ICE, new HashSet<PokemonType>() {{ addAll(Arrays.asList(DRAGON,FLYING,GRASS,GROUND)); }});
    put(NORMAL, new HashSet<PokemonType>());
    put(POISON, new HashSet<PokemonType>() {{ addAll(Arrays.asList(GRASS)); }});
    put(PSYCHIC, new HashSet<PokemonType>() {{ addAll(Arrays.asList(FIGHTING,POISON)); }});
    put(ROCK, new HashSet<PokemonType>() {{ addAll(Arrays.asList(BUG,FIRE,FLYING,ICE)); }});
    put(STEEL, new HashSet<PokemonType>() {{ addAll(Arrays.asList(ICE,PSYCHIC)); }});
    put(WATER, new HashSet<PokemonType>() {{ addAll(Arrays.asList(FIRE,GROUND,ROCK)); }});
  }};

  public float getModifier(PokemonType opponentType) {
    if (PokemonType.superEffective.get(this).contains(opponentType))
      return 2.0f;
    if (PokemonType.notVeryEffective.get(this).contains(opponentType))
      return 0.5f;
    if (PokemonType.noEffect.get(this).contains(opponentType))
      return 0.0f;
    return 1.0f;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String shortName() {
    return this.name.substring(0, 3);
  }

  private PokemonType(String name) {
    this.name = name;
  }

  public static void main(String[] args) {
    assert(PokemonType.ELECTRIC.getModifier(PokemonType.WATER) == 2.0f);
    assert(PokemonType.GROUND.getModifier(PokemonType.DARK) == 1.0f);
    assert(PokemonType.FIRE.getModifier(PokemonType.DRAGON) == 0.5f);
    assert(PokemonType.NORMAL.getModifier(PokemonType.GHOST) == 0.0f);
  }
}

I would use an ImmutableMap or an UnmodifiableMap since the map(s) aren't supposed to be modified once they've been populated. 我会使用ImmutableMapUnmodifiableableMap,因为一旦填充了地图,就不应该对其进行修改。

Also, I would create a single Map<List<PokemonType>, Float> , where each list would contain two PokemonType objects (the first object would be the attacker and the second would be the defender, or vice versa - it doesn't matter as long as it's consistent). 另外,我将创建一个Map<List<PokemonType>, Float> ,其中每个列表将包含两个PokemonType对象(第一个对象是攻击者,第二个对象是防御者,反之亦然-没关系只要是一致的)。 Alternatively, I would create a single Map<PokemonTypePair, Float> , where PokemonTypePair is 或者,我将创建一个Map<PokemonTypePair, Float> ,其中PokemonTypePair

public class PokemonTypePair {
    final public PokemonType attacker;
    final public PokemonType defender;

    public boolean equals(Object obj) {
        if(obj == null) return false;
        else if(!(obj instanceof PokemonTypePair)) return false;
        else {
            PokemonTypePair other = (PokemonTypePair)obj;
            return this.attacker.equals(other.attacker) &&
                this.defender.equals(other.defender);
        }
    }

    public int hashCode() {
        return (997 * attacker == null ? 0 : attacker.hashCode()) ^
            (991 * defender == null ? 0 : defender.hashCode());
    }
}

The the float for each map entry would be 0.0, 0.5, 1.0, or 2.0; 每个地图条目的float将为0.0、0.5、1.0或2.0; alternatively, omit the map entries that would have a 1.0 value and assume that missing map entries correspond to a 1.0 value. 或者,忽略将具有1.0值的映射条目,并假定缺少的映射条目对应于1.0值。

If the pairings are reflexive (meaning it doesn't matter who is the attacker and who is the defender - I don't know how pokemon works), then you just need a PokemonType pokemon1 field and a PokemonType pokemon2 field; 如果配对是自反的(意味着谁是攻击者,谁是防御者,我并不知道pokemon的工作原理,这PokemonType pokemon1 ),那么您只需要一个PokemonType pokemon1字段和一个PokemonType pokemon2字段即可; put the PokemonType that's lower in alphabetical order in the pokemon1 field and the PokemonType that's higher in alphabetical order in the pokemon2 field, in order to simplify the equals method. 为了简化equals方法,将pokemon1字段中字母顺序较低的pokemon1pokemon1字段中字母顺序较高的pokemon2 Likewise, if you go with the List<List<PokemonType>> approach, sort the inner list in alphabetical order, or else use a List<Set<PokemonType>> instead. 同样,如果您使用List<List<PokemonType>>方法,请按字母顺序对内部列表进行排序,或者改用List<Set<PokemonType>>

This way, given any two pokemon types, you just need to look up the pair in a single map to find the multiplier, rather than having to check multiple maps. 这样,给定任意两种神奇宝贝类型,您只需要在单个映射中查找一对即可找到乘数,而不必检查多个映射。

If you want to quickly find the pairings that are ineffective / super effective / etc, then maintain separate lists or sets of the ineffective / super effective / etc pairings, ie List<List<PokemonType>> ineffectivePairing or List<PokemonPairing> ineffectivePairing 如果要快速查找无效/超级有效等的配对, List<List<PokemonType>> ineffectivePairing维护无效/超级有效等配对的单独列表或集合,即List<List<PokemonType>> ineffectivePairingList<PokemonPairing> ineffectivePairing

如果您有一个带有枚举键的Map或一个带有枚举值的Set,则使用EnumMap或EnumSet更为有效,因为它们是针对这种情况而设计的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM