如何创建不包含重复WeaponAccessory类型的集合?
确保WeaponAccessory集合中同类型唯一的实现方案
这是个很常见的需求——给武器做配件系统,确保同类型配件只能装一个。下面给你几种实用的实现方式,以Java为例(从类名来看应该是Java场景):
方案1:用HashMap以类型为键(最推荐)
利用HashMap的键唯一性,直接把配件的Class对象作为键,配件实例作为值。这样天然保证同类型配件只会存在一个,而且查询、添加、删除的效率都很高(O(1))。
首先定义基础的接口和实现类:
// 配件接口 public interface WeaponAccessory { String getEffect(); // 示例方法:返回配件效果 } // 抑制器实现 public class Suppressor implements WeaponAccessory { @Override public String getEffect() { return "降低枪声与后坐力"; } } // 扩容弹匣实现 public class ExtendedMagazine implements WeaponAccessory { @Override public String getEffect() { return "提升弹容量"; } }
然后是M16类的实现:
import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Collection; public class M16 { // 核心存储:键是配件类型,值是配件实例 private final Map<Class<? extends WeaponAccessory>, WeaponAccessory> accessories = new HashMap<>(); // 添加配件的方法,返回是否添加成功 public boolean addAccessory(WeaponAccessory accessory) { if (accessory == null) { throw new IllegalArgumentException("配件不能为null"); } Class<? extends WeaponAccessory> accessoryType = accessory.getClass(); // 检查类型是否已存在 if (accessories.containsKey(accessoryType)) { return false; // 已有同类型配件,添加失败 } accessories.put(accessoryType, accessory); return true; } // 获取所有配件(返回不可修改集合,防止外部破坏约束) public Collection<WeaponAccessory> getAccessories() { return Collections.unmodifiableCollection(accessories.values()); } // 根据类型快速获取配件 @SuppressWarnings("unchecked") public <T extends WeaponAccessory> T getAccessory(Class<T> type) { return (T) accessories.get(type); } // 根据类型移除配件 public boolean removeAccessory(Class<? extends WeaponAccessory> type) { return accessories.remove(type) != null; } }
优点:
- 实现简单,利用Java集合的天然特性避免重复
- 按类型查询配件的效率极高
- 代码易读易维护
方案2:自定义包装类+HashSet
如果更倾向于用Set来存储,可以创建一个包装类,让包装类的equals()和hashCode()基于配件的类型,这样HashSet会自动过滤同类型的元素。
// 配件包装类 class AccessoryWrapper { private final WeaponAccessory accessory; public AccessoryWrapper(WeaponAccessory accessory) { this.accessory = accessory; } public WeaponAccessory getAccessory() { return accessory; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AccessoryWrapper that = (AccessoryWrapper) o; // 比较配件的类型是否相同 return accessory.getClass().equals(that.accessory.getClass()); } @Override public int hashCode() { return accessory.getClass().hashCode(); } } // M16类实现 import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; public class M16 { private final Set<AccessoryWrapper> accessoryWrappers = new HashSet<>(); public boolean addAccessory(WeaponAccessory accessory) { if (accessory == null) { throw new IllegalArgumentException("配件不能为null"); } // HashSet的add方法会自动判断是否重复(基于包装类的equals/hashCode) return accessoryWrappers.add(new AccessoryWrapper(accessory)); } public Set<WeaponAccessory> getAccessories() { return accessoryWrappers.stream() .map(AccessoryWrapper::getAccessory) .collect(Collectors.toUnmodifiableSet()); } }
缺点:需要额外编写包装类,代码量稍多;按类型查询配件需要遍历集合,效率不如HashMap。
方案3:普通集合+手动检查(适合小型集合)
如果你的配件数量很少,也可以用普通的List,在添加时手动遍历检查是否已有同类型元素:
import java.util.ArrayList; import java.util.List; public class M16 { private final List<WeaponAccessory> accessories = new ArrayList<>(); public boolean addAccessory(WeaponAccessory accessory) { if (accessory == null) { throw new IllegalArgumentException("配件不能为null"); } // 遍历检查是否已有同类型配件 boolean hasSameType = accessories.stream() .anyMatch(a -> a.getClass().equals(accessory.getClass())); if (hasSameType) { return false; } accessories.add(accessory); return true; } // 返回不可修改的列表,防止外部修改 public List<WeaponAccessory> getAccessories() { return List.copyOf(accessories); } }
缺点:每次添加都要遍历集合,性能随集合大小下降;查询同类型配件也需要遍历。
总结
如果追求性能和易用性,**方案1(HashMap)**是最优选择,它不仅能保证同类型唯一,还能快速按类型获取、删除配件,代码也最简洁。
内容的提问来源于stack exchange,提问作者MSOUFAN
相关产品推荐
相关产品推荐

