【问题标题】:how to iterate an ArrayList of objects and to access a method of that class to which the object belongs while iterating?如何迭代对象的 ArrayList 并在迭代时访问对象所属的类的方法?
【发布时间】:2015-08-05 14:59:33
【问题描述】:

我有一个类Employee 和该类中的一个方法getName(),它返回员工的姓名。每个员工都有一些属性(姓名、dob、职称、薪水),我将它们存储在一个 ArrayList 中。

现在我想编写一个方法deleteEmployee(String, ArrayList<Employee>),它将作为参数给出的字符串与员工姓名进行比较,如果找到任何匹配项,它将删除该/那些员工的全部详细信息 我已经尝试如下,但我遇到了错误,我不知道如何解决......

 public void deleteEmployee (String str,ArrayList <Employee> arr)
 {
    Employee obj2;

    for (int i = 0; i < arr.size(); i++)
    {
        if(str.equalsIgnoreCase(arr.get(obj2[i].getName())))
            arr.remove(obj2[i]);
        break;
    }
 }

【问题讨论】:

  • 你可以使用这个模式:stackoverflow.com/questions/223918/….
  • 这至少有 4 个问题。 obj2 从未被分配。 obj2 不是数组,所以你不能写 obj2[i]break 表示循环不循环。我也不明白arr.get(obj2[i].getName())arr.get 需要 int

标签: java


【解决方案1】:

你可能有一个 ConcurrentModificationException 或类似的东西。 那是因为你不能修改你正在迭代的数组,除非使用迭代器

你应该试试这样的

Iterator<Employee> it = arr.iterator();
Employee currentEmployee = null;
while(it.hasNext()){
   currentEmployee = it.next();
   if(currentEmployee.getName().equals(obj2.getName()){
      it.remove();
   }
}

为了帮助您将来解决问题,请同时发布您的错误和堆栈跟踪。

【讨论】:

  • 我认为这将是一个 IndexOutOfBoundsException - 因为 OP 没有使用迭代器,而是一个直到列表初始大小的 for 循环。但名单越来越小......
  • @Nick,根据合同迭代器永远不会抛出 IndexOutOfBoundsException。答案是正确的。
  • 几点注意事项:1)我们可以在循环中声明变量:“Employee currentEmployee = it.next();” 2) 从 ArrayList 中移除元素需要 O(n) 时间。
  • @Viktor 但原始问题使用 for 循环来遍历数组列表,而不是迭代器。
  • 在迭代数组时删除一个项目是获得异常的好方法。只有迭代器能够在迭代时移除。也没有 OutOfBoundException,即使在删除项目时也是如此。此外,如果他不需要 i 变量,他可以使用 for(Employee emp : arr)
【解决方案2】:

如果您只有一个与名称匹配的项目,您的方法将有效。 但是,您的错误在这里:

if(str.equalsIgnoreCase(arr.get(obj2[i].getName())))

相反,您需要从数组中获取对象,然后在结果上调用 getName:

if(str.equalsIgnoreCase(arr.get(i).getName()))

您还需要在if 块中使用您的breakif(...) { arr.remove(i); break; }

在您的实施中当然还有其他可以改进的地方。

【讨论】:

  • 我已经尝试过你提到的。但是,那么,如何删除那个对象???它只是“arr.remove(i);”吗? ???我已经写了...但是当我打印列表时,我发现没有删除第 i 个“员工”@Paul Bilnoski
  • @ArpanMukherjee 您是否将break 移动到if 内的块中?如果它仍然在外面,循环将在第一次迭代后中断,并且只有匹配的员工在列表中的第一位时才会显示成功。
  • 我已经完全去掉了break语句....我的显示函数如下... public void displayEmployees(ArrayList xyz) { for(Employee object:xyz) System.out. println("姓名 : "+object.getName()+", Employee-I'd : "+object.getEmployeeID()+", 出生日期 : "+formatterx.format(object.getDob())+ ", 职位: "+object.getDesignation()+", 薪水: "+object.getSalary()); } & 我打电话给 ob.deleteEmployee(p,arr); ob.displayEmployees(arr);其中“p”是字符串,“arr”是包含员工详细信息的数组列表
【解决方案3】:

据我所知,您的代码存在一些问题。

首先,使用break 不是很好的做法。尤其是在你用过的地方使用它。在您的代码中,if 语句处理后,for 循环结束。不管if 语句的结果如何,for 循环都不会迭代。因此,除非您只想检查所需员工是否在索引 0 处,否则这是不可取的。

for (int i = 0; i < arr.size(); i++)

这是第二个问题。由于您使用 break 语句,它在理想情况下运行良好,但如果所需的员工不在 ArrayList 中,您将获得 IndexOutOfBoundsException 因为在最后一次迭代中,您将尝试获得ArrayList 大小的索引,不存在。相反,你的 for 循环应该是

for (int i = 0; i < arr.size() - 1; i++)

这样,如果员工不在场,循环将在到达 ArrayList 的最后一个索引时停止,该索引比大小小 1。

另一个更直接的问题是这一行:

if(str.equalsIgnoreCase(arr.get(obj2[i].getName())))

在这一行中,您使用 Employee 对象作为参数调用 arr.get,而您应该使用 ArrayList 的索引。

if(str.equalsIgnoreCase(arr.get(i).getName()))

通过此修改,您调用 ArrayList 的索引,该索引将返回一个 Employee 对象。然后,您在该对象上调用 getName(),它会返回字符串,该字符串将与 str 进行比较,就像您打算做的那样。

最后一个问题是删除对象的行。

arr.remove(obj2[i]);

再次,您似乎试图访问 Employee 对象的索引,而不是 ArrayList。将此行更改为:

arr.remove(i);

会更有效。这样,您将删除数组的索引。您可以使用一个对象作为 remove() 方法的参数,但您首先需要将 i 的对象分配给 obj2,而且整个过程要麻烦得多。 因此,将所有内容放在一起,新的固定循环将是

for (int i = 0; i < arr.size() - 1; i++){
   if(str.equalsIgnoreCase(arr.get(i).getName())){
      arr.remove(i);
   }
}

假设只有一名员工具有给定名称,这不会有问题,但请注意,在遍历列表时删除 ArrayLists 中的对象存在问题。例如,如果您删除i 处的对象,则ArrayList 中它之后的对象都将向下移动一个索引。然后,如果您再次迭代,您将访问列表中i+1 的对象。但是,i+1 的 ACTUAL 对象是最初位于 i+2 的对象。因此,如果您删除 ArrayList 中的一个对象,您将跳过在下一次迭代中检查紧随其后的对象。 一个简单的解决方案是通过 ArrayList 迭代 BACKWARDS,这样当从列表中删除一个对象时,所有向下移动一个索引的对象都已经被检查过。对此还有其他更合适的解决方案,但向后迭代是一种简单的解决方法。

【讨论】:

  • 我试过这个,但是当我打印列表时,我发现第 i 个“员工”没有被删除
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-14
  • 1970-01-01
相关资源
最近更新 更多