【问题标题】:Removing item from ArrayList using remove(<index>) or remove(<objectRef>)使用 remove(<index>) 或 remove(<objectRef>) 从 ArrayList 中删除项目
【发布时间】:2016-02-06 14:40:51
【问题描述】:

我想创建一个程序,在要求用户输入他们想要删除的工资单号之前,在 ArrayList 中显示当前员工。然后,用户应输入三名员工之一的工资单号,然后按 Enter。按下回车后,程序应该从数组列表中删除该特定员工并再次显示整个列表(显然错过了他们删除的员工)。如果用户不再希望删除任何工资单编号,则工资单编号条目应为 0,然后应再次显示列表的内容。

我遇到的问题是删除部分。

有人向我推荐了两种实现这一目标的方法:

这个“搜索”方法应该返回 ArrayList 中的位置(以便可以使用 remove(&lt;index&gt;))或对对象的引用(以便可以使用 remove(&lt;objectRef&gt;))。如果未找到该职员,则搜索方法应返回 -1(如果正在使用 remove(&lt;index&gt;))或 null(如果正在使用 remove(&lt;objectRef&gt;))。

但是我不确定如何在 Java 中实现这一点。

这是我的文件结构:

ArrayListTest.java

import java.util.*;

import personnelPackage.Personnel;

public class ArrayListTest
{
    static Scanner keyboard = new Scanner(System.in);

    public static void main(String[] args)
    {
        long searchQuery;

        ArrayList<Personnel> staffList = new ArrayList<Personnel>();
        Personnel[] staff =
            {new Personnel(123456,"Smith","John"),
             new Personnel(234567,"Jones","Sally Ann"),
             new Personnel(999999,"Black","James Paul")};

        for (Personnel person:staff)
            staffList.add(person);

        do
        {
            showDisplay(staffList);

            System.out.print("\nPlease enter a payroll number to search: ");
            searchQuery = keyboard.nextLong();

            searchForPayrollNumber(staffList, searchQuery);


        }while(!(searchQuery == 0));


    }

    private static void showDisplay(ArrayList<Personnel> staffList)
    {
        System.out.print("\n------------- CURRENT STAFF LIST -------------\n");
        for (Personnel person : staffList)
        {
            System.out.println("Payroll number: " + person.getPayNum());
            System.out.println("Surname: " + person.getSurname());
            System.out.println("First name(s): " + person.getFirstNames() + "\n");
        }
    }

    public static void searchForPayrollNumber(ArrayList<Personnel> staffList, long searchQuery)
    {
        long index = staffList.indexOf(searchQuery);;

        for (Personnel person: staffList)
        {
            if (person.getPayNum() == searchQuery)
            {               
                System.out.print("\n------------- Staff member found and removed! -------------");
                System.out.println("\n\nFirst Name(s): " + person.getFirstNames());
                System.out.println("\nSurname: " + person.getSurname());
                System.out.print("\n-----------------------------------------------");

                staffList.remove(index);
                return;
            }
        }

        System.out.print("\n------------- No staff members found. Program terminated -------------");
        return;

    }

}

Personnel.java(在自己的名为personnelPackage的包中)

package personnelPackage;

public class Personnel
{
    private long payrollNum;
    private String surname;
    private String firstNames;

    public Personnel(long payrollNum, String surname, String firstNames)
    {
        this.payrollNum = payrollNum;
        this.surname = surname;
        this.firstNames = firstNames;
    }

    public long getPayNum()
    {
        return payrollNum;
    }

    public String getSurname()
    {
        return surname;
    }

    public String getFirstNames()
    {
        return firstNames;
    }

    public void setSurname(String newName)
    {
        surname = newName;
    }
}

【问题讨论】:

  • 您不能在增强的 for 循环中从列表中删除
  • “staffList.indexOf(searchQuery);”如何当 searchQuery 很长并且 staffList 是 ArrayList? 时工作
  • @ShireResident 这是因为来自Personnel.java 文件/ Personnel 类的getPayNum() 方法。
  • @Olehi - 它会返回 - 1,但因为您正在比较两种不同的类型。一个 long 与 Personnel 类,你没有实现 equals 方法或 hashcode 方法,所以如果你使用正确的类型,我认为 indexOf 不能正常工作

标签: java arraylist


【解决方案1】:

考虑使用Iterator 进行搜索和删除:

Iterator<Personnel> i = staffList.iterator();
while (i.hasNext()) {
    Personnel p = i.next();
    if (p.getPayNum() == searchQuery) {
        // print message
        i.remove();
        return p;
    } 
}
return null;

如果严格要求使用List#remove(),则返回找到的人员p并致电if (p != null) staffList.remove(p)

public static Personnel searchByPayNum(List<Personnel> ps, long num) {
    for (Personnel p : ps) {
        if (p.getPayNum() == num)
            return p;
    }
    return null;
}

在调用者代码中:

Personnel p = searchByPayNum(staffList, query);
if (p != null) {
    // log
    staffList.remove(p);
}

【讨论】:

  • 我相信问题中的要求是简单地实现一个返回对象或位置的搜索方法,而不是在同一方法中实际从集合中删除
  • @cricket_007 那么事情就简单多了,你知道的
  • 当然,但我没有写作业
  • 效率方面,返回索引更好,因为您正在执行两次线性遍历来查找元素,然后将其删除。 List#remove 也可能不起作用,因为在 Personnel 类上没有实现 equals 方法
  • @cricket_007 1) 同意,最好返回索引; 2) equals() 在这种特殊情况下不需要实现,因为从集合返回的对象直接作为remove() 参数传递——这里Object#equals() 可以工作。
【解决方案2】:
public static long searchForPayrollNumber(ArrayList<Personnel> staffList, long searchQuery) {
    //long index = staffList.indexOf(searchQuery);

for(int i = 0; i < staffList.size(); i++) {
    if (staffList.get(i).getPayNum() == searchQuery) {
        System.out.print("\n------------- Staff member found and removed! -------------");
        System.out.println("\n\nFirst Name(s): " + staffList.get(i).getFirstNames());
        System.out.println("\nSurname: " + staffList.get(i).getSurname());
        System.out.print("\n-----------------------------------------------");

        //staffList.remove(i);
        return i;
    }
}
System.out.print("\n------------- No staff members found. Program terminated -------------");
return -1;
}

【讨论】:

    【解决方案3】:

    您的搜索方法不应返回 void。它应该返回 int 或 long,

    public static long searchForPayrollNumber(ArrayList<Personnel> staffList, long searchQuery)
    {
     int index = -1;
     for (int i = 0; i < staffList.size(); i++){
         if(staffList.get(i).getPayNum() == searchQuery){
         index = i;
         System.out.print("\n------------- Found Staff member at position " + index + " in the list");
         break;         
         }
     } 
    if (index != -1){
        staffList.remove(index);
        System.out.print("\n------------- Removed the staff member");  
    }          
     return index;
    }
    

    最后一种方法返回了索引。现在当你想返回对象时:

    public static long searchForPayrollNumber(ArrayList<Personnel> staffList, long searchQuery)
    {
     Personnel p = null;
     for (int i = 0; i < staffList.size(); i++){
         if(staffList.get(i).getPayNum() == searchQuery){
         p = staffList.get(i);
         break;         
         }
     }          
     staffList.remove(p);     
     return p;
    } 
    

    你必须知道,从列表中删除它后,它会将所有后续元素向左移动(从它们的索引中减去一个)。

    另外,只是一个建议:

    而不是

    Personnel[] staff =
            {new Personnel(123456,"Smith","John"),
             new Personnel(234567,"Jones","Sally Ann"),
             new Personnel(999999,"Black","James Paul")};
    

    为什么不

    staffList.add(new Personnel(123456,"Smith","John"));
    staffList.add(new Personnel(234567,"Jones","Sally Ann"));
    staffList.add(new Personnel(999999,"Black","James Paul"));
    

    【讨论】:

      【解决方案4】:

      这只是一个建议。由于搜索和删除是您的主要目标,因此 ArrayList 不是要使用的正确集合。

      创建一个以 ID 为键、人员对象为值的 Hashmap。这将有助于在 O(1) 时间内识别人员并进行移除。

      ArrayList 只有在您知道要读取值的索引时才应使用。然后它在 O(1) 中执行此操作。如果不是,它是 O(n) 并且不如 HashMap 高效。

      【讨论】:

        猜你喜欢
        • 2015-06-15
        • 1970-01-01
        • 1970-01-01
        • 2015-06-10
        • 1970-01-01
        • 2022-07-23
        • 1970-01-01
        • 2020-08-29
        • 1970-01-01
        相关资源
        最近更新 更多