我们在开发中经常会用到集合,常用的有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; } } }