Удалить не работает в arraylist?

#java

#java

Вопрос:

Мне нужно выполнить проект, и я должен добавить людей в базу данных, а затем удалить их, но когда я пытаюсь удалить человека из arraylist, это работает, но когда я пытаюсь добавить больше, я получаю исключение index out of bounds?

 public void removePerson(List<Person> CrecheList) {
    if (CrecheList.isEmpty()) {
        JOptionPane.showMessageDialog(null, "You need a Child or parent in the database", "Error", JOptionPane.INFORMATION_MESSAGE);
    } else {
        String pickid = JOptionPane.showInputDialog(null, "Please Enter an id");
        int id = Integer.parseInt(pickid);
        Iterator<Person> i = CrecheList.iterator();
        while (i.hasNext()) {
            Person p = i.next();
            if (p.getID() == id) {
                i.remove();
            } else {
                JOptionPane.showMessageDialog(null, "There is no such person in the database", "Child name", JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }
}
  

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

Комментарии:

1. Пожалуйста, покажите нам также часть добавления.

2. Это какой-то сумасшедший отступ.

3. Итератор не гарантированно поддерживает .remove(). Он вызвал «NotImplementedException»?

4. @Paul: Я цитирую вопрос: «когда я пытаюсь удалить пользователя из arraylist, это работает» . Верно, заголовок вопроса довольно плохой и противоречивый.

5. @BalusC: Извините за комментарий. Я удалил его.

Ответ №1:

Полностью альтернативным подходом было бы реализовать equals() метод в вашем Person классе, чтобы он возвращал значение true, если ID поля равны:

 public class Person {
    int id;

    // Other fields/methods

    public boolean equals(Object o) {
        if (o instanceof Person) {
            Person p = (Person)o;
            if (this.id == p.getID()) return true;
        }
        return false;
    }
}
  

Если вы это реализуете, вам не нужно перебирать элементы — вы можете просто вызвать CrecheList.remove(p); .

Ответ №2:

Вместо этого передайте CopyOnWriteArrayList в вашу функцию удаления, которая допускает одновременные изменения, а затем:

 for ( Person p : CrecheList ) {
    if ( p.getID() == id ) {
      CrecheList.remove(p);
    }
}
  

Комментарии:

1. Чего мне не хватало, мне нужно было обновить массив, иначе он не знал, что он был удален.

Ответ №3:

(Это не ответ.)

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

 public void removePerson(List<Person> CrecheList) {
    if (CrecheList.isEmpty()) {
        emptyListError();
        return;
    }

    int id = getId();
    if (!removePersonById(id)) {
        couldNotRemoveError();
    }
}

public boolean removePersonById(int id) {
    Iterator<Person> i = CrecheList.iterator();
    while (i.hasNext()) {
        Person p = i.next();
        if (p.getID() == id) {
            i.remove();
            return true;
        }
    }

    return false;
}

// Swing-specific stuff.

public void emptyListError() {
    JOptionPane.showMessageDialog(null, "You need a Child or parent in the database", "Error", JOptionPane.INFORMATION_MESSAGE);
}

public int getId() {
    String pickid = JOptionPane.showInputDialog(null, "Please Enter an id");
    return Integer.parseInt(pickid);
}

public void couldNotRemoveError() {
    JOptionPane.showMessageDialog(null, "There is no such person in the database", "Child name", JOptionPane.INFORMATION_MESSAGE);
}
  

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

Ответ №4:

Попробуйте удалить пользователя вне повторяющегося цикла:

     Person p = null;

    while (i.hasNext()) { 
           p = i.next(); 
           if (p.getID() == id) { 
               break;
           }
           p = null;
    }            
    id ( p != null ) {
        CrecheList.remove( p );
    } 
    else { 
         JOptionPane.showMessageDialog(null, "There is no such person in the database", "Child name", JOptionPane.INFORMATION_MESSAGE); 
    } 
  

Комментарии:

1. Если итератор поддерживает .remove, то удаление в цикле итератора совершенно законно и работает нормально.

2. @Paul согласился, но у него проблемы с его кодом, так что это предложение обойти, мы не знаем реализацию списка и его итератора.

3. Если он не переопределил итератор, чтобы сделать что-то глупое, он должен либо правильно поддерживать .remove, либо он должен выдать исключение.