简体   繁体   English

通过迭代器从 ArrayList 中删除一个对象

[英]Delete an object from ArrayList by iterator

I want to create a program which would be like a home budget, so I have a class AmountModel (I know that Integer is not so good for id, but it's not a problem now):我想创建一个类似于家庭预算的程序,所以我有一个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.
}

And in another class I built this deleteAmount method:在另一个类中,我构建了这个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;
}

Adding object works good, but when I try to use the delete method I have to put first index.添加对象效果很好,但是当我尝试使用删除方法时,我必须将第一个索引。

Example:例子:
I have three objects (with index 0, 1, 2).我有三个对象(索引为 0、1、2)。

  • When I choose 1 or 2 program do nothing.当我选择 1 或 2 程序时,什么都不做。
  • When I choose 0 program deletes first index, remains index 1 and 2.当我选择 0 程序删除第一个索引时,保留索引 1 和 2。
  • When I choose 2, program do nothing.当我选择 2 时,程序什么也不做。
  • When I choose 1, program deletes index 1, remains index 2... etc.当我选择 1 时,程序删除索引 1,保留索引 2...等等。

What is wrong with this method?这种方法有什么问题?

You should separate your input logic from your delete logic and accept the list as a parameter.您应该将输入逻辑与删除逻辑分开,并接受列表作为参数。

Note: this only works with a mutable list.注意:这只适用于可变列表。 If you use something like Arrays.asList() it will throw an exception.如果你使用像 Arrays.asList() 这样的东西,它会抛出一个异常。

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

Welcome to Stack Overflow!欢迎使用堆栈溢出!

As others have mentioned, there are a few ways to tackle this.正如其他人所提到的,有几种方法可以解决这个问题。 But I think you can make this even simpler by changing the data structure used to access your AmountModel collection: if you're frequently accessing an item by ID, a Map is a great fit.但我认为您可以通过更改用于访问您的AmountModel集合的数据结构使这更简单:如果您经常通过 ID 访问项目,则Map非常适合。

No more worrying about iterator state;不再担心迭代器状态; you could just do something like:你可以这样做:

// 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
}

Hope this helps!希望这可以帮助! I threw together a working example in a gist here if you're interested.如果您有兴趣,我在这里汇总了一个工作示例。 (In Groovy, but should be enough to give you the idea) (在 Groovy 中,但应该足以给你这个想法)

Your break statement is breaking the while loop in the first iteration only.您的 break 语句仅在第一次迭代中中断 while 循环。 So, it will work only if the first am.getId() matches with your fist input.因此,只有当第一个 am.getId() 与您的第一个输入匹配时,它才会起作用。 Also, your sc.nextInt() will keep on scanning for next available input, Remove it from while loop.此外,您的 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;
}

call your sc.nextInt() outside of the loop, otherwise it will get run everytime the loop returns, as the condition gets reevaluated every time the loop ends.在循环外调用 sc.nextInt() ,否则每次循环返回时它都会运行,因为每次循环结束时都会重新评估条件。 also you could use the remove method of list你也可以使用列表的删除方法

    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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM