2013-07-28 2 views
2

Я новичок здесь, поэтому я не уверен, нормально ли иметь 2 вопроса в одном сообщении, поэтому, если я не должен просто сказать мне (красиво!), и я его изменю на один вопрос здесь и начать другое сообщение в другом месте.Строки визуально идентичны, но не совпадают; list iterator exception

Первая проблема:

Ниже в строках 5-8 я имею в виду две строки, которые мне нужно сравнить, чтобы увидеть, если они одинаковы. Я использую метод getUserInput(), чтобы получить ответ от пользователя на терминале, а затем у меня есть его, и напечатайте обе строки, чтобы я мог визуально осмотреть их, и они подходят к тому же. Тем не менее, раздел if, который должен запускаться, когда они такие же, никогда не запускается, а затем раздел else всегда делает это.

Вторая проблема:

В else разделе прямо ниже, когда здоровье currentChump «s сводится к < 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) 
+1

Я так счастлив, что кто-то считает меня замечательным. :) –

+2

В общем, вы должны [задавать отдельные вопросы отдельно] (http://meta.stackexchange.com/q/39223/193053). – Jeffrey

+0

Спасибо, Джеффри, я сделаю это в будущем. –

ответ

7

Использование Iterator для цикла в, если вы хотите, чтобы удалить элементы из списка и используйте Iterator.remove() вместо изменения списка.

Цитирование JavaDoc

... это вообще не допустимо для одного потока, чтобы изменить Коллекцию , а другой поток итерация над ним. В общем случае результаты итерации в этих обстоятельствах не определены. Некоторые реализации Iterator (в том числе реализации всех коллекций общего назначения , реализуемых JRE) могут выбрать исключение этого , если это обнаружено. Итераторы, которые делают это, - это , известные как отказоустойчивые итераторы, так как они терпят неудачу быстро и чисто, а не , что рискуют произвольным, недетерминированным поведением в неопределенном времени в будущем.

Обратите внимание, что это исключение не всегда указывает, что объект имеет , который был одновременно изменен другим потоком. Если один поток выдает последовательность вызовов методов, которые нарушают договор объекта, объект может вызывать это исключение. Например, , если поток изменяет коллекцию напрямую, когда он выполняет итерацию по коллекции с помощью отказоустойчивого итератора, итератор будет выбрасывать это исключение .

Обратите внимание, что отказоустойчивость быстрого поведения не может быть гарантировано, так как это, как правило, говоря, невозможно сделать какие-либо твердые гарантии в присутствии несинхронизированной одновременной модификации. Сбой при быстром запуске 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

+0

Может ли кто-нибудь быть таким добрым, чтобы научить меня, как использовать Итератор, чтобы переработать этот код? Я никогда раньше не использовал его, и я смотрел на него некоторое время, и я не понимаю его. У меня наверняка появился новый инструмент в моих словах для пакета инструментов! Спасибо всем за помощь! –

+0

Просьба предоставить [SSCCE] (http://sscce.org), я поможем вам в качестве воскресного выезда :) – Nishant

+0

Спасибо, Нишант. Теперь я собираюсь разобраться, что это такое! –

7

вы не можете использовать == для сравнения строк, как == сравнивает объекты ... не значение строк

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

должен быть

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

или

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

второй вопрос, кажется, что вы пытаетесь изменить объект (ваш список), который является частью другого потока.

+0

Вторая проблема неправильная. Это не многопоточность. Это удаление элемента из списка во время итерации по нему. Оператор '(Chump currentChump: chumpArray)' создает «Итератор» под капотом. –

4

Первая проблема

Всегда используйте equals при сравнении строк!

Что делает оператор ==, это проверить, являются ли объекты одним и тем же.

Единственная причина, по которой это, похоже, работает со строками, - это то, что называется interning.

Это означает, что, если конструктор String не был явно использован, ссылки с одной и той же последовательностью символов указывают на тот же объект String. Предполагается, что это сокращение использования памяти.

Вторая проблема

Exception in thread "main" java.util.ConcurrentModificationException 

Это вызвано изменение структуры вы перебор используя улучшенный цикл.

Этот link объясняет, почему выбрасывается Исключение.

В каждом следующем() вызов метода итератора,

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

метод вызывается, чтобы проверить, есть ли шанс сделан в списке. Это вызывает исключение ConcurrentModificationException в случае, если они не соответствуют .

Дополнительные комментарии

Ради конвенций, которые вы, кажется, отчасти уважал можно переименовать логическую переменную из PlayerIsAlive в isPlayerAlive. Это в camelCase с первым минусом и «есть», чтобы сразу указать читателю, что это значение true/false.

Смежные вопросы