Java集合如何根据自定义对象的某一个字段进行去重

我们在开发中经常会用到集合,常用的有ArrayList,HashSet,TreeSet等等。当集合是String、Int等基本数据类型的时候我们可以通过集合的contains()方法来实现比对是否存在。

但是当我们集合放的是我们自定义的对象应该怎么办呢?两个对象都是new出来的,对于集合来说,是两个不同的引用,这个时候直接使用contains()方法则无法实现。因为我们需要把自定义的对象改造一下。

改造之前我们还是想看看改造之前的例子吧。

我们先定义一个自定义类 Person 

public class Person {
   
   private String Name;
   private int age;
   private int sex;

   public String getName() {
      return Name;
   }

   public void setName(String name) {
      Name = name;
   }

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }

   public int getSex() {
      return sex;
   }

   public void setSex(int sex) {
      this.sex = sex;
   }
}

然后我们看下面这段代码,这段代码中,我们new了两个Person对象。属性值都是一摸一样的,其实这个时候应该是认为元素是重复得,但是由于我们是通过new出来的,因此其实HashSet是认为非重复元素,正常添加

        Person person = new Person();
        person.setName("P1");
        person.setAge(10);
        person.setSex(1);

        Person person2 = new Person();
        person2.setName("P1");
        person2.setAge(10);
        person2.setSex(1);

        HashSet<Person> hashSet = new HashSet<>();
        hashSet.add(person);
        hashSet.add(person2);

        //打印出来的结果是:hashSet: size 2
        Log.d("2635", "hashSet: size " + hashSet.size());

因此,我们需要改造一下Person,我们设定,只要Name是相同的,我们就认为是同一个对象,所以我们需要重写equals()和hashCode()两个方法,代码如下

public class Person {

   private String Name;
   private int age;
   private int sex;

   public String getName() {
      return Name;
   }

   public void setName(String name) {
      Name = name;
   }

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }

   public int getSex() {
      return sex;
   }

   public void setSex(int sex) {
      this.sex = sex;
   }

   @Override
   public boolean equals(Object o) {
//      注释部分是原来的自带的模板判断逻辑,我们需要修改这部分来实现我们需要的功能,只要Name相同,就认为是同一个对象
//      if (this == o) return true;
//      if (!(o instanceof Person)) return false;
//      Person person = (Person) o;
//      return age == person.age && sex == person.sex && Objects.equals(Name, person.Name);
      if (o == null) {
         return false;
      }

      if (this == o) {
         return true;
      }

      Person person = (Person) o;
      if (person.getName().equals(this.getName())) {
         return true;
      }


      return false;
   }

   @Override
   public int hashCode() {
//      注释部分是原来的自带的模板判断逻辑,我们需要修改这部分来实现我们需要的功能,只要Name相同,就认为是同一个对象
//      return Objects.hash(Name, age, sex);
      return Objects.hash(Name);
   }
}

改造之后,在运行上面的添加代码,就会发现,hashSet: size 1 ,也就是hashSet只会添加一个元素进去,只要Name这个属性是相同的,就认为是同一个属性。

题外话:HashSet是无法排序的,也就是说使用HashSet虽然可以去重,但是只能自然排序,那么一般我得做法是给对象添加一个时间值来排序,通过实现Comparable来实现,代码如下,代码我 为了方便,使用age字段来进行排序。

实际开发中,可能需要先进先出这种规则,那么我们就创建一个日期即可。

package com.himarking.dow.tables;

import android.util.Log;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Objects;
import java.util.concurrent.BlockingDeque;

public class Person implements Comparable{

   private String Name;
   private int age;
   private int sex;

   public String getName() {
      return Name;
   }

   public void setName(String name) {
      Name = name;
   }

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }

   public int getSex() {
      return sex;
   }

   public void setSex(int sex) {
      this.sex = sex;
   }

   @Override
   public boolean equals(Object o) {
//      注释部分是原来的自带的模板判断逻辑,我们需要修改这部分来实现我们需要的功能,只要Name相同,就认为是同一个对象
//      if (this == o) return true;
//      if (!(o instanceof Person)) return false;
//      Person person = (Person) o;
//      return age == person.age && sex == person.sex && Objects.equals(Name, person.Name);
      if (o == null) {
         return false;
      }

      if (this == o) {
         return true;
      }

      Person person = (Person) o;
      if (person.getName().equals(this.getName())) {
         return true;
      }


      return false;
   }

   @Override
   public int hashCode() {
//      注释部分是原来的自带的模板判断逻辑,我们需要修改这部分来实现我们需要的功能,只要Name相同,就认为是同一个对象
//      return Objects.hash(Name, age, sex);
      return Objects.hash(Name);
   }


   @Override
   public int compareTo(Object o) {
      if (!(o instanceof Person))  return -1;
      Person p = (Person) o;
      if (this.getAge()>((Person) o).getAge()){
         return -1;
      }else {
         return 1;
      }
   }
}

 

posted @ 2022-06-21 17:20  _Vincent  阅读(1919)  评论(0编辑  收藏  举报