Java内存存储排序列表值:现有方案是否存在内存浪费问题?
优化方案建议
核心问题分析
当前方案的主要问题在于:
- 重复维护多个结构相同的
EnumMap<SortType, List<String>>,代码冗余度高 - 存储ID字符串而非直接存储
Cosmetic对象,既增加了内存开销(重复存储字符串),又多了一次HashMap查找的性能损耗 - 预先初始化所有排序后的列表,即使某些排序类型从未被使用,也会占用内存
具体优化措施
1. 统一存储结构,消除代码冗余
首先定义枚举区分化妆品类型,替代单独的变量:
public enum CosmeticType { TRAIL, GADGET, SUIT, PET }
然后用一个统一的Map存储所有类型的排序后列表:
private final Map<CosmeticType, EnumMap<SortType, List<Cosmetic>>> sortedCosmetics = new EnumMap<>(CosmeticType.class);
后续新增类型只需扩展CosmeticType枚举,代码更易维护。
2. 直接存储Cosmetic对象,减少内存与性能损耗
把存储ID字符串改为直接存储Cosmetic对象引用:
- 避免重复存储ID字符串的内存开销(对象引用的内存占用远小于长字符串)
- 运行时无需再通过ID查询
cosmeticIDs,减少一次哈希表查找的性能消耗
3. 懒加载排序列表,降低初始内存占用
预先不初始化所有排序后的列表,在第一次请求某个SortType时才执行排序并缓存结果。结合统一的排序器Map复用排序逻辑:
首先定义全局排序器:
private static final Map<SortType, Comparator<Cosmetic>> SORT_COMPARATORS = Map.of( SortType.ALPHABETICALLY, Comparator.comparing(Cosmetic::getName), SortType.ALPHABETICALLY_REVERSE, Comparator.comparing(Cosmetic::getName).reversed(), SortType.RARITY, Comparator.comparingInt(Cosmetic::getRarity), SortType.RARITY_REVERSE, Comparator.comparingInt(Cosmetic::getRarity).reversed() );
然后实现懒加载逻辑,封装获取排序后列表的方法:
public List<Cosmetic> getSortedCosmetics(CosmeticType type, SortType sortType) { // 确保类型对应的EnumMap存在 EnumMap<SortType, List<Cosmetic>> typeMap = sortedCosmetics.computeIfAbsent(type, k -> new EnumMap<>(SortType.class)); // 懒加载并缓存排序后的列表 return typeMap.computeIfAbsent(sortType, k -> { // 获取该类型的所有Cosmetic(从cosmeticIDs中过滤对应类型) List<Cosmetic> allItems = cosmeticIDs.values().stream() .filter(cosmetic -> cosmetic.getType() == type) .collect(Collectors.toList()); // 使用对应排序器排序 allItems.sort(SORT_COMPARATORS.get(sortType)); return Collections.unmodifiableList(allItems); // 返回不可变列表避免外部修改 }); }
4. 分页逻辑简化
现在获取分页数据时直接操作Cosmetic列表即可,无需再查ID:
List<Cosmetic> gadgets = getSortedCosmetics(CosmeticType.GADGET, sortType); for (Cosmetic gadget : gadgets.subList(min, max)) { // 直接使用gadget对象加载 }
5. 可选:内存敏感场景的缓存策略
如果内存非常紧张,可以用软引用(SoftReference)存储排序后的列表,当JVM内存不足时自动回收缓存,下次请求时重新排序:
private final Map<CosmeticType, EnumMap<SortType, SoftReference<List<Cosmetic>>>> sortedCosmetics = new EnumMap<>(CosmeticType.class); public List<Cosmetic> getSortedCosmetics(CosmeticType type, SortType sortType) { EnumMap<SortType, SoftReference<List<Cosmetic>>> typeMap = sortedCosmetics.computeIfAbsent(type, k -> new EnumMap<>(SortType.class)); SoftReference<List<Cosmetic>> ref = typeMap.get(sortType); List<Cosmetic> list = ref != null ? ref.get() : null; if (list == null) { // 重新生成排序后的列表 List<Cosmetic> allItems = cosmeticIDs.values().stream() .filter(cosmetic -> cosmetic.getType() == type) .collect(Collectors.toList()); allItems.sort(SORT_COMPARATORS.get(sortType)); list = Collections.unmodifiableList(allItems); typeMap.put(sortType, new SoftReference<>(list)); } return list; }
总结优化效果
- 代码冗余度大幅降低,新增化妆品类型或排序规则更便捷
- 内存占用减少:去除重复ID字符串存储,懒加载避免无用列表占用内存
- 性能提升:直接操作
Cosmetic对象,减少哈希表查找开销 - 可维护性增强:排序逻辑集中管理,避免分散重复实现
内容的提问来源于stack exchange,提问作者Benna
相关产品推荐
相关产品推荐

