如何正确使用remove(Object o)删除ArrayList中的自定义对象(如何从ArrayList中删除特定的对象?)

在写java作业的时候遇到了以下问题:

自定义了一个worker泛型的ArrayList集合,添加元素后试图直接使用remove(Object o)方法传入一个worker类型的形参删除元素,结果删除失败。

试图百度该问题,结果搜到的结果大多不是直接告诉我用remove(int index)的那个重载就是告诉我它不行,它只适用于原始类型

翻了数页无果一气之下挖到底层才解决问题,希望该博客能帮到和我一样对此产生疑问但找不到答案的人

我们知道ArrayList集合给出了一个删除第一次出现的指定对象的删除元素方法remove(Object o)

但在大多数情况下,当arrayList包含用户自定义的数据类型的项时,此方法难以给出正确的结果。 网上的解释为:它只适用于原始数据类型。此时用户希望根据对象字段的值删除项,并且无法通过Remove函数进行比较。

 

针对以上情况,如果用户仍需要使用该remove(Object o)方法而不是另一个指定下标的remove(int index)方法重载,上述问题的解决方法为:在指定的用户自定义类中重载equals()方法。

e.g.

 public boolean equals(Object o) {
         worker w = (worker)o;//在equals函数中强转类型
         if(w.name == this.name && w.no == this.no && w.salary == this.salary)return true;
         else return false;
     }

为什么不直接使用worker类型的形参传入而用Object类型的形参,以及为何要重载equals()方法,是因为remove(Object o)的底层实现如下:

底层实现参考文章:ArrayList的底层实现原理 - maoyl - 博客园 (cnblogs.com)

  // 移除此列表中首次出现的指定元素(如果存在)。这是应为ArrayList中允许存放重复的元素。  
   public boolean remove(Object o) {  
      // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。  
      if (o == null) {  
          for (int index = 0; index < size; index++)  
              if (elementData[index] == null) {  
                  // 类似remove(int index),移除列表中指定位置上的元素。  
                  fastRemove(index);  
                  return true;  
              }  
      } else {  
          for (int index = 0; index < size; index++)  
              if (o.equals(elementData[index])) {  //注意此时的判断条件
                  fastRemove(index);  
                  return true;  
              }  
          }  
          return false;  
      } 
  } 

我们可以发现,在remove(Object o)方法中对于寻找要删除的元素时使用的判断条件为if (o.equals(elementData[index]))

所以我们可以通过重载equals()方法来自定义判断对象相等的条件

而在equals()方法中需要进行强制类型转换的原因是elementData的底层声明类型为Object

 
/** 
       * The array buffer into which the elements of the ArrayList are stored. 
       * The capacity of the ArrayList is the length of this array buffer. 
       */  
      private transient Object[] elementData;  
    
      /** 
       * The size of the ArrayList (the number of elements it contains). 
       * 
       * @serial 
       */  
      private int size;

由于不能保证elementData[index]在传入equals方法时一定为用户声明的自定义类型,所以最保险的方法就是在用户重载的equals()方法中进行一次强制类型转换。


以下为实例代码:

 import java.util.*;
 public class WorkerTest {
 ​
     public static void main(String[] args) {
         ArrayList<worker> a1 = new ArrayList<worker>();
         a1.add(new worker("1001","张三",3000));
         a1.add(new worker("1003","李四",3500));
         a1.add(new worker("1004","王五",2500));
         print(a1);
         if (a1.remove(new worker("1003","李四",3500)))System.out.println("成功删除员工信息!");
         else System.out.println("不存在该员工信息,删除失败!");
         print(a1);
         
     }
     public static void print(ArrayList <worker> a) {//遍历输出
         Iterator<worker> itr = a.iterator();
         while(itr.hasNext())
         {
             worker e = (worker) itr.next();
             System.out.println(e.toString());
         }
     }
 ​
 }
 class worker{
     private String no;//工号
     private String name;//姓名
     private double salary;//工资
     public worker(String no, String name, double salary) {
         this.no = no;
         this.name = name;
         this.salary = salary;
     }
     public String toString() {
         String s = this.no + "号工人" + this.name + ",每月工资为" + this.salary + "元";
         return s;
     }
     public boolean equals(worker w) {//此时没有进行强制类型转换
         if(w.name == this.name && w.no == this.no && w.salary == this.salary)return true;
         else return false;
     }
 //私有成员的get和set方法略
 }

以下为重写了equals()方法但没有进行强制类型转换的运行结果:

 

在以上样例的equals()方法中添加强制类型转换:

 public boolean equals(Object o) {
         worker w = (worker)o;//在equals函数中强转类型
         if(w.name == this.name && w.no == this.no && w.salary == this.salary)return true;
         else return false;
     }

以下为重写了equals()方法且进行强制类型转换的运行结果:

 

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值