【问题标题】:How can you test and see if everything in a String[] is in an ArrayList<String>如何测试并查看 String[] 中的所有内容是否都在 ArrayList<String> 中
【发布时间】:2018-01-16 12:41:05
【问题描述】:

我正在制作一款扑克游戏,我试图测试看看是否有玩家手中有皇家同花顺。然而,在我进行测试之前,我遇到了一个障碍:我没有一种快速简单的方法来测试每个玩家的 A、K、Q、J 和 10 的手牌。
到目前为止,这是我的代码:

private void findWinner() {
    // p1 hand
    List<String> p1hand = cards.subList(10, 15);
    p1hand.addAll(cards.subList(0, 2));
    System.out.println("Player 1's total hand is " + p1hand);
    // p1 hand
    List<String> p2hand = cards.subList(10, 15);
    p2hand.addAll(cards.subList(2, 4));
    System.out.println("Player 2's total hand is " + p2hand);
    // testing for royal flush
    String[] spadeRoyalFlush = {"Ace of spades", "King of spades", "Queen of spades", "Jack of spades", "10 of spades"};
    String[] heartRoyalFlush = {"Ace of hearts", "King of hearts", "Queen of hearts", "Jack of hearts", "10 of hearts"};
    String[] dimRoyalFlush = {"Ace of diamonds", "King of diamonds", "Queen of diamonds", "Jack of diamonds", "10 of diamonds"};
    String[] clubRoyalFlush = {"Ace of clubs", "King of clubs", "Queen of clubs", "Jack of clubs", "10 of clubs"};
    // p1
    boolean p1royalFlush = false;
    if(p1hand.contains(spadeRoyalFlush)) { // line 104
        p1royalFlush = true;
    }
    if(p1hand.contains(heartRoyalFlush)) {
        p1royalFlush = true;
    }
    if(p1hand.contains(dimRoyalFlush)) {
        p1royalFlush = true;
    }
    if(p1hand.contains(clubRoyalFlush)) {
        p1royalFlush = true;
    }
    if(p1royalFlush) {
        System.out.println("Player 1 got a royal flush with " + p1hand);
    }
    // p2
    boolean p2royalFlush = false;
    for(int i=0; i<p2hand.size(); i++) {
        if(p2hand.contains(spadeRoyalFlush)) {
            p2royalFlush = true;
        }
        if(p2hand.contains(heartRoyalFlush)) {
            p2royalFlush = true;
        }
        if(p2hand.contains(dimRoyalFlush)) {
            p2royalFlush = true;
        }
        if(p2hand.contains(clubRoyalFlush)) {
            p2royalFlush = true;
        }
    }
    if(p2royalFlush) {
        System.out.println("Player 2 got a royal flush with " + p2hand);
    }
} // line 165 is where I call this method

cards 是一个字符串数组列表,其中包含每张牌的每个名称(例如“黑桃 A”、“红桃 3”等)
当我运行这段代码时,我得到了错误:

Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$SubList.checkForComodification(Unknown Source)
at java.base/java.util.ArrayList$SubList.listIterator(Unknown Source)
at java.base/java.util.AbstractList.listIterator(Unknown Source)
at java.base/java.util.ArrayList$SubList.iterator(Unknown Source)
at java.base/java.util.AbstractCollection.contains(Unknown Source)
at poker.PlayGame.findWinner(PlayGame.java:104)
at poker.PlayGame.doEverything(PlayGame.java:165)
at poker.MainPoker.main(MainPoker.java:7)

我研究了这意味着什么,我感到很震惊,因为据我所知,我没有对代码中的任何内容进行迭代。
这是 DoEverything 方法:

public void doEverything() {
    dealHands();
    throwCards();
    findWinner(); // line 165
}

这是主要的方法:

public static void main(String[] args) {
    PlayGame game = new PlayGame();
    game.doEverything(); // line 7
}

【问题讨论】:

  • 遍历数组并调用 list.contains(currentIterationElement);现在,如果其中之一在列表中,则将其设置为 true。或者,您可以在 if 语句中使用 && 运算符(逻辑 AND 运算符)
  • 您可能需要改写标题,因为它几乎不能反映您的问题。请显示其余代码并标记/突出显示错误消息中指定的行(第 7、104 和 165 行)。
  • @Turing85 我标记为 104,165 是我在其中调用此方法的公共 void,而 7 是我在 165 处调用该方法的位置,是我的主要方法。
  • @TheMagician Again:请发布代码。没有看到相关部分,(即至少方法 main(...)doEverything(...),我们无法判断为什么会发生此异常。
  • @TheMagician 请查看链接的副本。 TL;DR:你得到Exception,因为你在结构上修改了subListdocumentation of List::subList(int, int) 声明:“返回的列表受此列表的支持,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。”

标签: java arrays string arraylist


【解决方案1】:

我会使用List.containsAll() 记录的here

如果此列表包含指定集合的​​所有元素,则返回 true。

String[] array = ...;
List<String> list = ....;
list.containsAll(Arrays.asList(array));

重新读取第 104 行的 ConcurrentModificationException,您在 p1hand 上调用 contains(),但 p1hand 来自 cards.subList(10, 15)

我们看不到cards 的来源。您尚未发布必要的代码来调试该点。但请参阅@devpuh 的答案,了解有关在子列表中调用contains() 的更多详细信息。

【讨论】:

  • 一个问题:这是在 if 语句中还是作为布尔值,还是以任何一种方式工作?
  • @TheMagician 我们应该怎么知道?此调用返回true iff。 array 中的所有 Strings 也在 listfalse 中。
  • 一个问题:我的问题仍然存在错误。
  • @TheMagician 那么你应该清楚你的实际问题是什么。如果您的问题是关于ConcurrentModificationException,那么这就是问题所在;如果您要对List&lt;String&gt; 中的所有String[] 进行测试,这就是我的回答。我建议你问第二个问题,并将这两个问题分开。
【解决方案2】:

小心List.subList(int fromIndex, int toIndex)

返回此列表在指定 fromIndex(包括)和 toIndex(不包括)之间部分的视图。 (如果 fromIndex 和 toIndex 相等,则返回列表为空。)返回列表由此列表支持,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。

(...)

如果后备列表(即此列表)以除通过返回列表之外的任何方式进行结构修改,则此方法返回的列表的语义将变为未定义。 (结构性修改是改变这个列表的大小,或者以其他方式扰乱它,使得正在进行的迭代可能产生不正确的结果。)

此创建列表的所有更改都会影响原始列表!

当原始列表的结构发生变化时,当您尝试访问子列表时,您会立即获得ConcurrentModificationException。 (在您的情况下,您在列表中添加了一个新元素 cards

改变

List<String> p1hand = cards.subList(10, 15);
p1hand.addAll(cards.subList(0, 2));

List<String> p1hand = new ArrayList<>(cards.subList(10, 15)); // create a new list
p1hand.addAll(cards.subList(0, 2));

并检查列表是否包含所有特定卡使用

p1hand.containsAll(Arrays.asList(spadeRoyalFlush));

【讨论】:

  • "此创建列表上的所有更改都将影响原始列表!" - 您忽略了文档的一个重要部分:"[...] 所以 返回列表中的非结构性变化反映在此列表中,反之亦然。"
  • @Turing85 感谢只阅读了 JavaDoc 的一部分。现在已经包含了所有必要的文档并改进了答案。
猜你喜欢
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 2018-04-19
  • 2020-02-11
  • 1970-01-01
  • 2015-07-08
  • 2019-12-29
  • 1970-01-01
相关资源
最近更新 更多