【问题标题】:Java: remove all objects with iteratorJava:使用迭代器删除所有对象
【发布时间】:2014-11-21 11:58:51
【问题描述】:

我正在创建一个库类,它将类书的对象存储在 ArrayList 集合中。我拥有大部分功能,但是我想要一个删除函数,在调用时删除参数(名称)的所有对象。到目前为止我所做的函数似乎只是删除它遇到的第一个元素,然后停止执行。

我的库类看起来像这样(省略添加对象的代码):

import java.util.ArrayList;
import java.util.Iterator;

public class Library {
    private ArrayList<Book> collection;
    private Book book;

public Library() {
    collection = new ArrayList<Book>();

}

public Book findBook(String searchBook) {

    Book bookB = null;
    Iterator<Book> it = collection.iterator();
    boolean found = false;

    while (it.hasNext() && !found) {
        bookB = it.next();
        String b = book.getBookName();

        if (b.equals(searchBook)) {
            found = true;

        }
    }

    if (found) {
        return bookB;
    }
    else {
        return null;
    }
}

public void removeBook (String searchBook) { 

    if (findBook(searchBook) != null && bookname.equals(searchBook)) {
        Book b = findBook(searchBook);
        System.out.println("Removed " + b.getBookName());
        collection.remove(b);
    }
    else {
        System.out.println("Don't worry, we don't have that one anyways");
    }
}

}

我的一个朋友告诉我创建一个 foreach 循环来将 if/else 包装在 removeBook 中,但到目前为止我没有成功,因为老实说我不知道​​如何实现它。

非常感谢任何帮助、见解或反馈。

【问题讨论】:

  • 您在寻找Iterator#remove() 吗?
  • 是的,我需要遍历集合中的所有对象,然后删除每个具有相同名称的对象(字符串)

标签: java foreach while-loop iterator


【解决方案1】:

您需要遍历 list 的所有元素,然后检查与您作为参数传递给 removeBook 方法的书名相同的书名,如果找到这样的条目,则通过迭代器的 remove 方法将其删除。所以代码应该是这样的:

Iterator<Book> it = collection.iterator();
Book book;
while (it.hasNext()) {
    book = it.next();
    if (book.getBookName().equals(searchBook)) {
        it.remove();
    }
}

【讨论】:

    【解决方案2】:

    你可能想要类似的东西

    Book b = findBook(searchBook);
    while(b != null) {
        collection.remove(b);
        b = findBook(searchBook);
        ...
     }
    

    【讨论】:

    • 我尝试了该函数并且它可以编译,但是当我尝试执行它时返回 java.langNullPointerException: null in String b = book.getBookName();
    • 您可能在某处将空对象插入到列表中。由于您总是在执行 book = it.next() 之前测试 it.hasNext(),因此 book 将始终是列表的某个元素。您可以在提取其名称之前测试它是否为空,但这并不好,最好能弄清楚代码中的空书在哪里插入到列表中。
    【解决方案3】:

    findBook(searchBook) 方法中的 while (it.hasNext() &amp;&amp; !found) 在找到名称作为参数传递的书后停止。并返回 book。这就是为什么只删除一个带有name 的对象的原因。更改您的代码以返回具有该名称的所有对象的list。只需检查返回类型booksFound 是否有像booksFound.Size &gt; 0 这样的书籍。然后遍历列表并删除它们。

    public List<Book> findBook(String searchBook) {
    
    Book bookB = null;
    Iterator<Book> it = collection.iterator();
    List<Book> booksFound = new ArrayList<Book>();
    
    while (it.hasNext()) {
        bookB = it.next();
        String b = book.getBookName();
    
        if (b.equals(searchBook)) {
            booksFound.add(b);
        }
    }
    return booksFound;
    }
    

    以及remove方法:

    public void removeBook (String searchBook) { 
    
    List<Books> booksFound = findBook(searchBook);
    if(booksFound.size() > 0) {
       for (Book book: booksFound) {
          collection.remove(book);
       }
    }
    else {
        System.out.println("Don't worry, we don't have that one anyways");
    }
    }
    

    【讨论】:

    • 似乎很复杂,我必须进行如此多的更改才能应用如此(相对)小的功能。我是一个完整的java初学者,当然会听取这里给出的任何建议,但难道不应该比这更容易吗?注意:我尝试了顶级评论的解决方案,效果很好。与常规对象迭代相比,使用您所描述的列表有什么优势吗?
    • 在编程中,代码的简单性和灵活性之间总是存在平衡。上面的代码可能看起来更长或更复杂,但如果您将来必须进行更改,则非常灵活。您可以将findBook(arg) 方法用于应用程序中的不同任务。如果您将此程序限制为一个特定任务,您将需要编写另一种方法。因此,您最终将一遍又一遍地编写相同的方法,这是多余的,并且会使代码维护变得困难。编码时始终考虑程序的未来使用。方便代码的扩展和维护。
    猜你喜欢
    • 2011-12-31
    • 2015-10-05
    • 1970-01-01
    • 2012-11-30
    • 2014-07-12
    • 2016-12-02
    • 2020-07-30
    • 1970-01-01
    • 2011-07-17
    相关资源
    最近更新 更多