字符串在视觉上相同但不匹配;列出迭代器异常

时间:2013-07-28 02:55:53

标签: java

我是新来的,所以我不确定在同一篇文章中是否可以有两个问题,所以如果我不应该只是告诉我(很好!)我会把它改成一个在这里提问并在其他地方开始另一篇文章。

第一个问题:

下面的第5-8行我指的是我需要比较的两个字符串,看它们是否相同。我正在使用getUserInput()方法从终端的用户那里获得响应,然后我将它继续打印并打印两个字符串,以便我可以直观地检查它们,并且它们也是相同的。但是,应该在它们相同时运行的if部分永远不会运行,然后else部分始终会运行。

第二个问题:

在下面的else部分,每当currentChump的健康状况降至< 1时,我就会得到一些我以前从未见过的例外情况知道该做些什么。

这是我的代码,然后在下面我将粘贴异常:

for (Chump currentChump : chumpArray) {
    System.out.println(" ");
    String playerChoice = helper.getUserInput(
                          "Type the name of the Weapon that you wish to use.");
    System.out.println(playerChoice);
    System.out.println(currentChump.getWeakness().toLowerCase());
    if (currentChump.getWeakness().toLowerCase() == playerChoice) {
        chumpArray.remove(currentChump);
    } // END IF
    else {
        while (PlayerIsAlive && currentChump.getHealth() > 0) {
            int damage = (int) Math.floor((Math.random() * 6) + 1);
            System.out.println(currentChump.getName() + " has "
                             + currentChump.getHealth() + "health remaining.");
            currentChump.setHealth(currentChump.getHealth() - damage);
            System.out.println("You hit the enemy for " 
                             + damage + " points of damage.");
            System.out.println(currentChump.getName() + " has " 
                             + currentChump.getHealth() + " health remaining.");
    System.out.println(" ");
            if (currentChump.getHealth() < 1) {
                chumpArray.remove(currentChump);
            } // END IF
            else {
                int damage2 = (int) Math.floor((Math.random() * 4) + 1);
                player.setHealth(player.getHealth() - damage2);
                if (player.getHealth() < 1) {
                    PlayerIsAlive = false;
                } // END IF
            } // END WHILE
        } // END ELSE
    } // END ELSE
} // END FOR

异常:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at ArenaGameCopy.startPlaying(ArenaGameCopy.java:87)
at ArenaGameCopy.main(ArenaGameCopy.java:168)

3 个答案:

答案 0 :(得分:7)

如果要从列表中删除项目并使用Iterator.remove()而不是修改基础列表,请使用Iterator循环。

引用JavaDoc

  

...一个线程通常不允许修改Collection   而另一个线程正在迭代它。一般来说,结果   在这些情况下,迭代是不确定的。一些迭代器   实现(包括所有通用集合的实现)   JRE提供的实现可以选择抛弃它   检测到此行为的异常。执行此操作的迭代器是   称为失败快速迭代器,因为它们快速而干净地失败   冒着不确定的任意,非确定性行为的风险   未来的时间。

     

请注意,此异常并不总是表示对象具有   由另一个线程同时修改。如果是单线程   发出一系列违反合同的方法调用   一个对象,该对象可能抛出此异常。例如,如果a   线程在迭代时直接修改集合   使用失败快速迭代器进行集合,迭代器将抛出此异常   异常。

     

请注意,通常情况下无法保证快速失败的行为   说话,在场的情况下不可能做出任何硬性保证   不同步的并发修改。失败快速操作投掷   ConcurrentModificationException是尽力而为的。因此,它   编写一个依赖于此异常的程序是错误的   它的正确性:应该只使用ConcurrentModificationException   检测错误。


让我帮助你。阅读代码中的注释:

import java.util.*;

/**
  Hello! Welcome to basics.
  This is what called a SSCCE.
  Next time anyone asks for it, do it.
  Because, 90% of the times, creating SSCCE will help you identify the issue.
  Hope you learn something from these lines.

  To compile and execute this code do the following:
  a. Paste this class from import to last closed bracket in a 
     file named Test.java
  b. javac Test.java
  c. java Test
  Bliss!
*/
public class Test{

  public static void main(String[] args){
    // 1. Do not worry about these lines
    //    I am just creating some sample data
    List<String> chumpArray = Arrays.asList("Oh my god! You must know to create SSCCE".split("\\s"));
    chumpArray = new ArrayList<String>(chumpArray);
    System.out.println("List to be iterated: " + chumpArray);

    // 2. This is what I meant when I said to use an Iterator
    //    Obviously, your iterator will look like Iterator<Chump>
    for(Iterator<String> chumpIt = chumpArray.iterator(); chumpIt.hasNext();) {

        // 3. Materialize the current item
        String currentChump = chumpIt.next();
        System.out.println("Currently on: " + currentChump);

        // 3. String comparison
        //    ==            WRONG
        //    .equals       RIGHT
        if (currentChump.toLowerCase().equals("you")) {
          System.out.println("DELETING: " + currentChump);
          // 4. Just ask the iterator to remove the current Item
          chumpIt.remove();
          // Was it really so hard?!
        }
    }
    System.out.println("List after delete: " + chumpArray);
  }
}

执行此操作后,我们

tmp$ java Test
List to be iterated: [Oh, my, god!, You, must, know, to, create, SSCCE]
Currently on: Oh
Currently on: my
Currently on: god!
Currently on: You
DELETING: You
Currently on: must
Currently on: know
Currently on: to
Currently on: create
Currently on: SSCCE
List after delete: [Oh, my, god!, must, know, to, create, SSCCE]

HTH
NISHANT

答案 1 :(得分:7)

你不能使用==比较字符串==将比较对象...而不是字符串的值

if (currentChump.getWeakness().toLowerCase() == playerChoice)

应该是

if (currentChump.getWeakness().toLowerCase().equals(playerChoice))

 if (currentChump.getWeakness().equalsIgnoreCase(playerChoice))

第二个问题似乎是你试图修改属于另一个线程的对象(你的列表)。

答案 2 :(得分:4)

第一个问题

比较字符串时始终使用equals

==运算符的作用是检查对象是否相同。

这似乎与字符串一起使用的唯一原因是因为interning

这意味着,除非显式使用了String构造函数,否则具有相同字符序列的引用指向同一个String对象。这应该是为了减少内存使用量。

第二个问题

Exception in thread "main" java.util.ConcurrentModificationException

这是通过使用增强的for循环修改您正在迭代的结构引起的。

这个link解释了抛出异常的原因。

  

在迭代器的每个next()方法调用中,

  final void checkForComodification() {
      if (modCount != expectedModCount)
    throw new ConcurrentModificationException();
  }
     调用

方法,检查列表中是否有机会。   这将抛出ConcurrentModificationException,以防它们不这样做   匹配。

其他评论

为了您似乎已部分尊重的约定,您可以将布尔变量从PlayerIsAlive重命名为isPlayerAlive。这是在camelCase中,第一个小写和“是”立即向读者表明它是真/假值。