Java 24(IntelliJ社区版)中如何为HashSet实现固定顺序以有序展示游戏成就
Java 24(IntelliJ社区版)中如何为HashSet实现固定顺序以有序展示游戏成就
我懂你现在的困扰:想用HashSet带来的高效查找特性,又希望游戏成就严格按照你定义的顺序(比如先金币类、再点击类,从低到高难度)展示,但HashSet本身就是无序且不保证遍历顺序的,所以你现在看到的成就列表顺序混乱很正常。下面给你两个既能保留HashSet高效性,又能实现固定展示顺序的解决方案,结合你的代码直接改就行:
方案一:用LinkedHashSet替代HashSet(最省心的方案)
LinkedHashSet是HashSet的子类,它会在HashSet的基础上用一个双向链表维护元素的插入顺序,也就是说你添加元素的顺序就是遍历的顺序,同时它的contains()、add()等核心方法的时间复杂度还是O(1),完全满足你要的高效性。
具体修改步骤:
- 在
AchievementManager类里,把allAchievements的声明从HashSet改成LinkedHashSet:
import java.util.LinkedHashSet; // 替换原有HashSet声明 LinkedHashSet<String> allAchievements = new LinkedHashSet<>();
- 调整
GamePanel的openAchievementMenu方法里的遍历逻辑:
原来你为了应对HashSet的无序用了Collections.reverse,现在LinkedHashSet已经能保留插入顺序了,直接遍历allAchievements就行,去掉反转的冗余代码:
// 删掉这段无效的反转代码 // java.util.List<String> reversedList = new java.util.ArrayList<>(achievementManager.allAchievements); // Collections.reverse(reversedList); // 直接遍历LinkedHashSet,就是你定义的顺序 for (String achievement : achievementManager.allAchievements) { boolean isUnlocked = achievementManager.unlockedAchievements.contains(achievement); achievementManager.createNewButton(achievement, isUnlocked); }
这样遍历出来的顺序就是你初始化块里添加的顺序:coin10 → coin500 → coin1000000 → click50 → click250 → click1000,完全符合预期。
方案二:单独维护展示顺序列表(兼容原有HashSet)
如果你不想替换HashSet,也可以单独维护一个固定顺序的成就ID列表,用HashSet负责快速的存在性检查,用列表控制展示顺序:
具体修改步骤:
- 在
AchievementManager里添加一个固定顺序的列表,同时用这个列表初始化allAchievements:
import java.util.Arrays; import java.util.List; // 固定展示顺序的列表,完全按照你想要的顺序定义 private List<String> achievementDisplayOrder = Arrays.asList( "coin10", "coin500", "coin1000000", "click50", "click250", "click1000" ); // 用列表初始化HashSet,保留高效查找特性 HashSet<String> allAchievements = new HashSet<>(achievementDisplayOrder);
- 在
GamePanel的openAchievementMenu里遍历这个顺序列表:
// 遍历固定顺序的列表,而不是无序的HashSet for (String achievement : achievementManager.achievementDisplayOrder) { boolean isUnlocked = achievementManager.unlockedAchievements.contains(achievement); achievementManager.createNewButton(achievement, isUnlocked); }
这样不管HashSet的内部顺序怎么变,展示顺序都由你定义的列表牢牢控制,同时allAchievements的高效查找特性也完全保留。
额外小提示:修复代码里的笔误
我注意到你achievementCheck方法里有个容易忽略的bug:
// 这里判断的是"coins1000000"(多了个s),和解锁的ID不匹配 if(stats.getMoney() >= 1000000 && !unlockedAchievements.contains("coins1000000")){ unlock("coin1000000"); }
会导致100万金币的成就永远无法触发,记得把判断里的ID改成"coin1000000"哦~
备注:内容来源于stack exchange,提问作者user27209652
相关产品推荐
相关产品推荐

