[英]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. 我会使用ImmutableMap或UnmodifiableableMap,因为一旦填充了地图,就不应该对其进行修改。
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
字段中字母顺序较低的pokemon1
和pokemon1
字段中字母顺序较高的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>> ineffectivePairing
或List<PokemonPairing> ineffectivePairing
如果您有一个带有枚举键的Map或一个带有枚举值的Set,则使用EnumMap或EnumSet更为有效,因为它们是针对这种情况而设计的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.