如何创建双Key的HashMap?单类实现双键取值方案
嘿,这个需求我熟——想要一个能通过Player对象+字符串标识(比如"fly"、"speed")双键定位值的HashMap,还得只用一个类实现对吧?这就给你安排一个简洁靠谱的方案:
双键HashMap实现方案(单类版本)
核心思路
我们可以在单个类里封装一个普通HashMap,不过把Player和字符串标识打包成一个复合键作为HashMap的键。关键是要给这个复合键正确实现equals()和hashCode()方法,确保只有当两个键(Player和标识字符串)都完全匹配时,才会被HashMap识别为同一个键。
完整代码实现(泛型灵活版)
这个版本支持任意键类型,如果你后续需要扩展其他键类型也能用:
import java.util.HashMap; import java.util.Objects; public class DoubleKeyHashMap<K1, K2, V> { // 内部用普通HashMap存数据,键是我们自定义的复合键 private final HashMap<Key, V> internalMap = new HashMap<>(); // 内部复合键类,仅当前类可见,不用对外暴露 private class Key { private final K1 firstKey; private final K2 secondKey; public Key(K1 firstKey, K2 secondKey) { this.firstKey = firstKey; this.secondKey = secondKey; } // 必须重写equals,保证两个键都匹配才相等 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Key key = (Key) o; return Objects.equals(firstKey, key.firstKey) && Objects.equals(secondKey, key.secondKey); } // 必须重写hashCode,让相同的复合键生成相同的哈希值 @Override public int hashCode() { return Objects.hash(firstKey, secondKey); } } // 对外的存值方法,直接传两个键和对应值 public void put(K1 firstKey, K2 secondKey, V value) { internalMap.put(new Key(firstKey, secondKey), value); } // 对外的取值方法,传两个键就能拿到对应值 public V get(K1 firstKey, K2 secondKey) { return internalMap.get(new Key(firstKey, secondKey)); } // 可选:添加移除方法 public V remove(K1 firstKey, K2 secondKey) { return internalMap.remove(new Key(firstKey, secondKey)); } // 可选:获取当前存储的键值对数量 public int size() { return internalMap.size(); } }
针对你的需求优化(固定键类型版)
如果不需要泛型的灵活性,直接把第一个键固定为Player,第二个固定为String,代码会更贴合你的场景:
import java.util.HashMap; import java.util.Objects; public class PlayerAttributeStore { private final HashMap<Key, Integer> internalMap = new HashMap<>(); private class Key { private final Player player; private final String attributeType; public Key(Player player, String attributeType) { this.player = player; this.attributeType = attributeType; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Key key = (Key) o; return Objects.equals(player, key.player) && Objects.equals(attributeType, key.attributeType); } @Override public int hashCode() { return Objects.hash(player, attributeType); } } public void savePlayerAttribute(Player player, String attributeType, Integer value) { internalMap.put(new Key(player, attributeType), value); } public Integer getPlayerAttribute(Player player, String attributeType) { return internalMap.get(new Key(player, attributeType)); } }
使用示例
假设你的Player类已经正确实现了equals()和hashCode()(这很重要,不然复合键的匹配会出错),使用起来非常简单:
// 创建Player对象 Player bob = new Player("Bob"); PlayerAttributeStore store = new PlayerAttributeStore(); // 存储Bob的飞行和速度属性 store.savePlayerAttribute(bob, "fly", 15); store.savePlayerAttribute(bob, "speed", 8); // 获取属性值 Integer bobFlyLevel = store.getPlayerAttribute(bob, "fly"); // 返回15 Integer bobSpeedLevel = store.getPlayerAttribute(bob, "speed"); // 返回8
关键注意事项
- 一定要确保
Player类正确实现了equals()和hashCode(),否则复合键无法正确识别同一个Player对象 - 内部的
Key类是私有,对外完全透明,用户只需要调用暴露的put/get方法即可,不用关心内部实现 - 整个逻辑都封装在一个类里,完全符合你“仅使用一个类”的要求
内容的提问来源于stack exchange,提问作者LoopTurn
相关产品推荐
相关产品推荐

