Object中的equals()方法默認是按地址比較,而不按內容進行比較,java
public boolean equals(Object obj) { return (this == obj); }
在String中覆寫了Object中的equals方法,以用於判斷字符串是否相同,安全
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對象,同姓名同年齡,視爲同一個對象,數據結構
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():this
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方法。spa
自定義比較器:線程
當元素自身不具有比較性,或者具有的比較性不是所須要的,這時須要讓容器自身具有比較性。
當兩種排序都存在時,以比較器爲主。
方式1:定義一個類,實現Comparable接口,覆蓋compareTo方法。code
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集合的構造函數。 blog
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()); } } }