Java: ошибка времени выполнения при удалении в списке массивов

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

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

Первый вызов метода удаления работает и успешно удаляет элемент для вызываемого студенческого идентификатора. Однако второе удаление дает мне ошибку исключения одновременной модификации.

Следующий код создает список массивов Student и вызывает метод удаления (дважды).

static ArrayList<Student> myRoster = new ArrayList<>();

public static void main(String[] args)
{
    // add students to the roster
    add("1", "John", "Smith", "[email protected]", "20", 
    88, 79, 59);
    add("2", "Suzan", "Erickson", "[email protected]", "19", 
    91, 72, 85);
    add("3", "Jack", "Napoli", "The_lawyer99yahoo.com", "19", 
    85, 84, 87);
    add("4", "Erin", "Black", "[email protected]", "22", 
    91, 98, 82);

    //loop through the ArrayList and for each element:
    remove("3");
    remove("3");

Вот метод удаления. Вот мои текущие мысли о том, как это должно работать:

* Чтобы сначала проверить, существует ли идентификатор учащегося, я помещаю if/else, чтобы удалить учащегося во встроенном цикле if/else.

* Я использую, чтобы видеть, содержит ли список массива идентификатор студента. Если да, то выполняется удаление if/else. Если это не так, он выдает распечатку ошибки и возвращается.

    public static void remove(String studentID)
    //remove student from roster by student ID
    //print error message if student is not found
    {
        for(Student b: myRoster)
        {
            String record = b.getStudentID();
            Boolean a = studentID.contains(studentID);
            if (a)
            {
                Boolean c = record.matches(studentID);
                if (c)
                {
                    myRoster.remove(b);
                    System.out.println("Student ID " + studentID + " was removed.");
                }
            else
                {
                    ;
                }  
            }
            else
            {
                System.out.println("Student ID does not exist.");
            }

Вот ошибка, которую я получаю:

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at Roster.remove(Roster.java:48)
at Roster.main(Roster.java:28)
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at Roster.remove(Roster.java:48)
at Roster.main(Roster.java:28)

Любые идеи?


person John Wood    schedule 08.03.2017    source источник
comment
Вы не можете использовать remove в цикле foreach. Используйте обычный цикл for.   -  person D M    schedule 09.03.2017
comment
Возможный дубликат Ошибка программирования Java: java.util.ConcurrentModificationException   -  person D M    schedule 09.03.2017


Ответы (3)


Вы не можете безопасно изменять содержимое списка, проходя по нему с помощью итератора. Для этого используйте ListIterator.

ListIterator<Student> it = myRoster.listIterator();
while (it.hasNext()) {
    Student b = it.next();
    if (b.getStudentId() == studentId) {
        it.remove(); // Removes b from myRoster
    }
    ...
}

Обратите внимание, что это не будет хорошо масштабироваться, если будет много студентов. Вам лучше иметь Map<String, Student> для хранения вашего списка, а ключи - это студенческие билеты.

person pmorken    schedule 08.03.2017

Разве вы не хотели бы сказать, что студенческий билет не существует в первой части вашего цикла else, которую вы оставили пустой?

if (a)
{
    Boolean c = record.matches(studentID);
    if (c)
    {
        myRoster.remove(b);
        System.out.println("Student ID " + studentID + " was removed.");
    }
    else
    {
        System.out.println("Student ID does not exist.");
    }  
}
person trex    schedule 08.03.2017

Попробуй это:

for(Iterator<String> it = myRoster.iterator(); it.hasNext();) {
    String b = it.next();
    ...
    if (...) {
        it.remove();
        ...
    }
    ...
}
person Kiryl    schedule 08.03.2017