我想知道是否有更好的方法来创建和搜索下面的静态映射。如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);
}
}
我会使用ImmutableMap或UnmodifiebleMap,因为映射在填充后不应该被修改。
此外,我会创建一个Map<List<PokemonType>, Float>
,其中每个列表都包含两个PokemonType
对象(第一个对象是攻击者,第二个对象是防御者,反之亦然——只要一致就没关系)。或者,我会创建一个单独的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());
}
}
每个映射条目的float
将是0.0、0.5、1.0或2.0;或者,省略将具有1.0值的映射条目,并假设丢失的映射条目对应于1.0值。
如果配对是反射性的(这意味着谁是攻击者,谁是防御者并不重要——我不知道pokemon是如何工作的),那么你只需要一个PokemonType pokemon1
字段和一个PokemonType pokemon2
字段;将字母顺序较低的PokemonType放在pokemon1
字段中,将字母顺序较高的PokemonType放在pokemon2
字段中,以简化equals
方法。同样,如果使用List<List<PokemonType>>
方法,请按字母顺序对内部列表进行排序,或者使用List<Set<PokemonType>>
。
这样,给定任意两种pokemon类型,您只需要在单个映射中查找这对即可找到乘数,而不必检查多个映射。
如果您想快速找到无效/超有效等配对,请维护无效/超高效等配对的单独列表或集合,即List<List<PokemonType>> ineffectivePairing
或List<PokemonPairing> ineffectivePairing
如果您有一个带有Enum键的Map或一个带有枚举值的Set,那么使用EnumMap或EnumSet会更有效,因为它们是为这种情况设计的。