• 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;
          }
       }
    }
  • 相关阅读:
    ADO.NET 六(DataRow DataColumn)
    ADO.NET 五(DataAdapter 与 DataSet)
    ADO.NET 四(DataReader)
    ADO.NET 三(Command)
    ADO.NET 二(Connection)
    面试知识点笔记-1
    【新弹性盒】
    设置弹性盒要用到的属性
    Vue项目模板--和--webpack自动化构建工具的---项目打包压缩使用
    Vue中使用【watch检测路由】的方法
  • 原文地址:https://www.cnblogs.com/linfenghp/p/16397605.html
Copyright © 2020-2023  润新知