【问题标题】:How to search an array list for a string and remove it如何在数组列表中搜索字符串并将其删除
【发布时间】:2019-11-29 02:00:52
【问题描述】:

我必须为我的初学者 Java 类做一个与继承有关的项目。 MediaItem 类封装了表示 MediaItem 所需的数据。这是已经给出的代码:

 public class MediaItem {



  protected String title;
  protected String author;
  protected String genre;

  /* Subclasses may add specific parameters to their constructor's
   * parameter lists.
  */
  public MediaItem(String title, String author, String genre){
    this.title = title;
    this.author = author; 
    this.genre = genre;
  }
  // get method for the title
  public String getTitle(){
     return title;
  }
  // get method for the author
  public String getAuthor(){
     return author;
  }
  // get method for the genre
  public String getGenre(){
     return genre;
  }

  // Subclasses should override.
  public String toString(){
     return title+", "+author+", "+genre;
  }
}

MediaList 类封装了用户收藏中的媒体项目列表。该列表实现为 MediaList 类型的 ArrayList。每种类型的媒体项目都由 Book、Movie、Podcast 或 Song 类的实例表示。这些类是 MediaItem 的子类。该列表将媒体项存储为 MediaItem 类型的引用。
这是MediaList中添加和删除项目的代码:

public void addItem(MediaItem newItem){
      itemList.add(newItem);
   }
public boolean removeItem(String targetTitle, String targetAuthor){
      boolean result = false;  
      for (MediaItem media : itemList) {
         if(itemList.contains(targetTitle) && itemList.contains(targetAuthor)){
            itemList.remove(media);
            result = true;
         } else {
            result = false;
         }
      }
      return result;
   }

当这个测试用 Junit 运行时,会抛出一个错误,说期望大小是 但它应该是 当我运行它并回答提示时,它说媒体项目已添加,但当我尝试删除媒体项目时,它显示“在库中找不到 Black Panther,没有任何内容被删除。”

@Test 
   public void addOneRemoveOneItemUpdateSizeTest() {
      MediaItem item = new Movie("Black Panther", "Coogler", "fantasy", 134, "Chadwick Boseman", "2018");
      mediaList.addItem(item);
      mediaList.removeItem("Black Panther", "Coogler");
      int studentSize = mediaList.getNumItems(); 
      assertEquals("Test 30: Add item, remove item size is 0.", 0, studentSize);

Movie

public class Movie extends MediaItem {

 public Movie(String title, String author, String genre, 
              int playTime, String leadActor, String releaseYear){
  super(title, author, genre);
  playTime = 0;
  leadActor = "noLead";
  releaseYear = "noRelease";
 }


 public int getPlayTime(){
  return playTime;
 }

 public String getLeadActor(){
  return leadActor;
 }

 public String getReleaseYear(){
  return releaseYear;
 }

@Override
public String toString(){
  super.toString();
  return "Movie: " + title + ", " + author + ", " + genre + ", " + playTime + ", " + leadActor + ", " + releaseYear;  
}
}

我的 removeItem 方法错了吗?我不明白为什么找不到标题。有人能指出我正确的方向吗?

【问题讨论】:

  • 你能提供你的Movie类吗?
  • 您在迭代列表时不得修改列表。您可以手动使用Iterator,然后,您可以在其上使用remove() 来删除当前元素,或者在使用Java 8 时,使用public boolean removeItem(String targetTitle, String targetAuthor) { return itemList.removeIf(media -> media.getTitle().equals(targetTitle) && media.getAuthor().equals(targetAuthor)); }
  • @MaxPeng 刚刚添加

标签: java arraylist collections


【解决方案1】:

我认为问题在于if 声明:

if(itemList.contains(targetTitle) && itemList.contains(targetAuthor)){

应该是

if (media.getTitle().equals(targetTitle) && media.getAuthor().equals(targetAuthor))

换句话说,您需要检查每个媒体项目(而不是列表)是否具有正确的标题和作者。

【讨论】:

    【解决方案2】:

    这段代码有两个修正点:-

    1. 条件语句不正确
    2. 删除操作不正确,将导致 ConcurrentModification 异常

    1。条件语句Bug说明


    contains() 方法检查列表中是否存在传递的对象。它在处理包装类或字符串类时很方便,但是当我们有自定义数据类型(例如类和用例要求)根据某些属性删除对象时,这种方法可能没有帮助。

    现在您的代码正在检查参数“targetTitle”和“targetAuthor”中的字符串对象,因此无法从列表中删除所需的对象。

    您的用例要求根据 MediaItem 类的属性(实例变量)“title”和“author”从列表中删除对象,因此当您遍历列表中的所有对象时,您应该检查您在列表中遍历的对象的相应实例变量。

    请使用 '==' 而不是 equals() 方法,因为您必须进行显式的 null 检查,否则最终可能会出现 NullPointer 异常。


    2。从列表中错误删除


    您正在对通过 for-each(Enhanced for) 循环遍历的同一对象进行修改。为此,您应该使用迭代器对象。请通过此链接了解更多信息。Using iterator for deleting elements in collection

    【讨论】:

      【解决方案3】:

      我认为您以错误的方式删除项目。您应该从列表末尾使用迭代器或循环从列表中删除项目。

      此外,条件语句也是错误的,您应该使用 String.equals 来检查与输入匹配的项目属性。此外,您应该验证输入以防止出现空指针异常。

      【讨论】:

      • 我尝试从列表末尾开始循环并使用迭代器,但是当我编写条件语句 if(MediaItem.getTitle().equals(targetTitle) && MediaItem.getAuthor().equals(targetAuthor)){ 时,我收到一条错误消息“非静态方法 getTitle() 和 getAuthor( ) 不能从静态上下文中引用"
      • @adenn this call MediaItem.getTitle() 尝试调用属于类本身静态方法,而您需要在当前项目上调用它(迭代器指向的类实例,即 object)。 MediaItem item = iterator.next(); if (targetTitle.equals(item.getTitle() & targetAuthor.equals(item.getAuthor())) { iterator.remove(); } 并且不要忘记在方法的开头检查 targetTitletargetAuthornull
      猜你喜欢
      • 1970-01-01
      • 2015-11-05
      • 2018-07-05
      • 1970-01-01
      • 2019-12-22
      • 1970-01-01
      • 2020-09-29
      • 2019-07-23
      • 2015-10-11
      相关资源
      最近更新 更多