Java中的equals方法和自定义比较器
Object中的equals()方法默认是按地址比较,而不按内容进行比较,
1 2 3 | public boolean equals(Object obj) { return ( this == obj); } |
在String中覆写了Object中的equals方法,以用于判断字符串是否相同,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public boolean equals(Object anObject) { if ( this == anObject) { return true ; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0 ; while (n-- != 0 ) { if (v1[i] != v2[i]) return false ; i++; } return true ; } } return false ; } |
"上帝"Object中equals方法可以被子类重写,然后多态调用,当我们要自定义对象比较时一般要覆写equals方法,比如有Person对象,同姓名同年龄,视为同一个对象,
1 2 3 4 5 6 7 | public boolean equals(Object obj) { if (!(obj instanceof Person)) return false ; Person p = (Person)obj; return this .name.equals(p.name) && this .age == p.age; } |
List集合判断元素是否相同,依据是元素的equals方法。
如果要将自定义对象存入到HashSet中,则要覆写hashCode()和equals():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public int hashCode() { //System.out.println(this.name+"....hashCode"); return name.hashCode()+age* 11 ; } public boolean equals(Object obj) { if (!(obj instanceof Person)) return false ; Person p = (Person)obj; //System.out.println(this.name+"....equals..."+p.name); return this .name.equals(p.name) && this .age==p.age; } |
HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet是如何保证元素唯一性的呢?是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
自定义比较器:
当元素自身不具备比较性,或者具备的比较性不是所需要的,这时需要让容器自身具备比较性。
当两种排序都存在时,以比较器为主。
方式1:定义一个类,实现Comparable接口,覆盖compareTo方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | class Student implements Comparable //该接口强制让学生具备比较性。 { private String name; private int age; Student(String name, int age) { this .name = name; this .age = age; } //先按年龄从小到大排序,如果年龄相同,再按名字 public int compareTo(Object obj) { if (!(obj instanceof Student)) throw new RuntimeException( "不是学生对象" ); Student s = (Student)obj; if ( this .age>s.age) return 1 ; if ( this .age==s.age) { return this .name.compareTo(s.name); } return - 1 ; } public String getName() { return name; } public int getAge() { return age; } } class Test { public static void main(String[] args) { TreeSet ts = new TreeSet( new Mycompare()); ts.add( new Student( "lisi02" , 22 )); ts.add( new Student( "lisi02" , 21 )); ts.add( new Student( "lisi007" , 20 )); ts.add( new Student( "lisi09" , 19 )); ts.add( new Student( "lisi06" , 18 )); ts.add( new Student( "lisi06" , 18 )); ts.add( new Student( "lisi007" , 29 )); Iterator it = ts.iterator(); while (it.hasNext()) { Student stu = (Student)it.next(); System.out.println(stu.getName()+ "..." +stu.getAge()); } } } |
方式2:定义一个类,还要再自定义一个比较器来实现Comparator接口,覆盖compare方法。
定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | class Student { private String name; private int age; Student(String name, int age) { this .name = name; this .age = age; } public String getName() { return name; } public int getAge() { return age; } } //自定义比较器:先按名字来排序,如果名字相同再按年龄 class Mycompare implements Comparator { public int compare(Object o1,Object o2) { Student s1 = (Student)o1; Student s2 = (Student)o2; int num = s1.getName().compareTo(s2.getName()); if (num == 0 ) return new Integer(s1.getAge()).compareTo( new Integer(s2.getAge())); return num; } } class Test { public static void main(String[] args) { TreeSet<Student> ts = new TreeSet<Student>( new Mycompare()); ts.add( new Student( "lisi02" , 22 )); ts.add( new Student( "lisi02" , 21 )); ts.add( new Student( "lisi007" , 20 )); ts.add( new Student( "lisi09" , 19 )); ts.add( new Student( "lisi06" , 18 )); ts.add( new Student( "lisi06" , 18 )); ts.add( new Student( "lisi007" , 29 )); for (Iterator<Student> it = ts.iterator();it.hasNext() ; ) { Student stu = it.next(); System.out.println(stu.getName()+ ".." +stu.getAge()); } } } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· 趁着过年的时候手搓了一个低代码框架
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现