You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 00:26:30