Java扑克游戏检测皇家同花顺时遇ConcurrentModificationException问题求助
解决你的扑克游戏问题:ConcurrentModificationException与皇家同花顺检测优化
先解决你遇到的ConcurrentModificationException异常问题,再给出高效的皇家同花顺检测方案。
一、解决ConcurrentModificationException异常
异常原因分析
你代码中出现这个异常的核心问题,是误用了List.subList()返回的视图列表:
cards.subList(10, 15)返回的不是独立新列表,而是原cards列表的视图,它和原列表共享同一个修改计数器(modCount)。- 当你调用
p1hand.addAll(cards.subList(0, 2))时,本质是修改了原cards列表的结构(视图的修改会同步到原列表),这会让原列表的modCount数值增加。 - 后续调用
p1hand.contains(...)时,方法内部会遍历这个视图列表,遍历过程中会检查当前modCount是否和创建视图时的数值一致,发现不一致就抛出ConcurrentModificationException。
解决方案
不要直接使用subList返回的视图,而是创建独立的新ArrayList来存储玩家手牌,让新列表和原列表完全解耦:
// 修改p1hand的创建方式 List<String> p1hand = new ArrayList<>(cards.subList(10, 15)); p1hand.addAll(cards.subList(0, 2)); // 同理修改p2hand的创建方式 List<String> p2hand = new ArrayList<>(cards.subList(10, 15)); p2hand.addAll(cards.subList(2, 4));
这样后续调用contains或其他迭代操作时,就不会再触发修改检查、抛出异常了。
二、高效检测皇家同花顺的方案
你当前的检测逻辑有两个明显问题:一是List.contains(Object o)只能检查列表中是否存在单个元素,无法判断是否包含数组里的所有元素;二是没有考虑玩家是从7张牌中选5张组成牌型的规则。
优化思路
皇家同花顺的核心是同一花色的A、K、Q、J、10,我们可以通过以下步骤高效检测:
- 将玩家的7张牌按花色分组,记录每个花色下包含的所有点数。
- 检查是否存在某个花色的点数集合,完全包含
{"Ace", "King", "Queen", "Jack", "10"}这五个点数。
具体实现代码
// 定义皇家同花顺需要的点数集合(提前初始化,避免重复创建) private static final Set<String> ROYAL_RANK_SET = new HashSet<>(Arrays.asList("Ace", "King", "Queen", "Jack", "10")); // 检测手牌是否包含皇家同花顺的方法 private boolean hasRoyalFlush(List<String> hand) { // 按花色分组:key是花色,value是该花色下的所有点数集合 Map<String, Set<String>> suitToRanks = new HashMap<>(); for (String card : hand) { // 拆分牌的点数和花色(格式为"X of Y") String[] parts = card.split(" of "); String rank = parts[0]; String suit = parts[1]; // 将点数加入对应花色的集合中 suitToRanks.computeIfAbsent(suit, k -> new HashSet<>()).add(rank); } // 遍历每个花色的点数集合,检查是否覆盖皇家同花顺的所有点数 for (Set<String> ranks : suitToRanks.values()) { if (ranks.containsAll(ROYAL_RANK_SET)) { return true; } } return false; }
使用方式
在你的findWinner方法中,直接调用这个方法即可:
// 检测玩家1是否有皇家同花顺 boolean p1royalFlush = hasRoyalFlush(p1hand); if (p1royalFlush) { System.out.println("Player 1 got a royal flush with " + p1hand); } // 检测玩家2是否有皇家同花顺 boolean p2royalFlush = hasRoyalFlush(p2hand); if (p2royalFlush) { System.out.println("Player 2 got a royal flush with " + p2hand); }
方案优势
- 高效性:只需要遍历7张牌一次完成分组,再对每个花色的点数集合做一次检查,时间复杂度为O(n)(n为手牌数量,这里固定是7)。
- 准确性:正确处理了7张牌选5张的规则,只要某一花色包含所有皇家同花顺的点数,就判定为符合条件。
- 可扩展性:如果后续需要检测其他牌型(比如同花顺、四条等),可以基于这个分组逻辑快速扩展。
内容的提问来源于stack exchange,提问作者user9010885




