【问题标题】:Delete an object from ArrayList by iterator通过迭代器从 ArrayList 中删除一个对象
【发布时间】:2020-06-22 15:48:32
【问题描述】:

我想创建一个类似于家庭预算的程序,所以我有一个课程AmountModel (我知道Integer对id不太好,但现在没问题了):

import java.time.LocalDate;

public class AmountModel {
  private Integer id;
  private Double amount;
  private CategoryModel categoryModel;
  private LocalDate localDate;

  // getters/setters etc.
}

在另一个类中,我构建了这个deleteAmount 方法:

static Scanner sc = new Scanner(System.in);

public List<amountModel> deleteAmount() {
    Iterator<AmountModel> it = amountList.iterator();
    while (it.hasNext()) { 
        System.out.println("Choose index to delete ");
        AmountModel am = it.next();
        if (am.getId().equals(sc.nextInt())) {
            it.remove();
        }
        break;
    }
    return amountList;
}

添加对象效果很好,但是当我尝试使用删除方法时,我必须放置第一个索引。

示例:
我有三个对象(索引为 0、1、2)。

  • 当我选择 1 或 2 程序时,什么都不做。
  • 当我选择 0 时,程序会删除第一个索引,保留索引 1 和 2。
  • 当我选择 2 时,程序什么也不做。
  • 当我选择 1 时,程序会删除索引 1,保留索引 2...等等。

这个方法有什么问题?

【问题讨论】:

  • System.our.println 和对sc.nextInt() 的调用移到循环之外。否则,您将为列表中的每个项目请求一次索引。
  • 我认为您的 sc.nextInt() 调用需要在 while 循环之外,以便比较列表中的每个索引。目前,您每次读取要删除的索引时只比较单个列表项。
  • if (am.getId().equals(sc.nextInt())) { 这在很多层面上都不是一个好主意。按照@Jamie 的建议去做。

标签: java arraylist iterator


【解决方案1】:

您应该将输入逻辑与删除逻辑分开,并接受列表作为参数。

注意:这只适用于可变列表。如果你使用 Arrays.asList() 之类的东西,它会抛出异常。

public void deleteAmount(List<AmountModel> list, int key) {
    list.removeIf(a -> a.getId().equals(key));
}

【讨论】:

    【解决方案2】:

    欢迎来到 Stack Overflow!

    正如其他人所提到的,有几种方法可以解决这个问题。但我认为您可以通过更改用于访问您的 AmountModel 集合的数据结构来使这更加简单:如果您经常通过 ID 访问项目,Map 非常适合。

    不再担心迭代器状态;你可以这样做:

    // Map "amounts" by ID for easy O(1) lookup.
    static Map<Integer, AmountModel> amountMap
    
    public void deleteAmount(Integer id) {
      if (!amountMap.containsKey(id)) { 
        // (TODO: Handle invalid input)
        throw new Exception()
      }
    
      amountMap.remove(id)
      return
    }
    

    希望这会有所帮助!如果您有兴趣,我在 gist here 中整理了一个工作示例。 (在 Groovy 中,但应该足以给你这个想法)

    【讨论】:

      【解决方案3】:

      您的 break 语句仅在第一次迭代中中断 while 循环。因此,只有当第一个 am.getId() 与您的第一个输入匹配时,它才会起作用。 此外,您的 sc.nextInt() 将继续扫描下一个可用输入,将其从 while 循环中删除。

      static Scanner sc = new Scanner(System.in);
      public List<AmoutModel> deleteAmount() {
          Iterator<AmoutModel> it = amountList.iterator();
          Integer scId = sc.nextInt();
          while (it.hasNext()) { 
              System.out.println("Choose index to delete ");
              AmoutModel am = it.next();
              if (am.getId().equals(scId)) {
                  it.remove();
                  break;
              }
          }
          return amountList;
      }
      

      【讨论】:

        【解决方案4】:

        在循环外调用你的 sc.nextInt() ,否则每次循环返回时它都会运行,因为每次循环结束时都会重新评估条件。 也可以使用 list 的 remove 方法

            static Scanner sc = new Scanner(System.in);
            public List<AmoutModel> deleteAmount() {
                System.out.println("Choose index to delete ");
                int index = sc.nextInt();
                amountList.remove(index);
                return amountList;
            }
        

        【讨论】:

          猜你喜欢
          • 2014-05-04
          • 1970-01-01
          • 2016-02-14
          • 2012-11-30
          • 1970-01-01
          • 2014-07-12
          • 1970-01-01
          • 2020-03-18
          • 2018-07-24
          相关资源
          最近更新 更多