在Java中Object類是所有類的父類,其中有幾個需要override的方法比如equals,hashCode和toString等方法。
每次寫這幾個方法都要做很多重復(fù)性的判斷, 很多類庫提供了覆寫這幾個方法的工具類,
Guava也提供了類似的方式。下面我們來看看Guava中這幾個方法簡單使用。
equals方法: equals是一個經(jīng)常需要覆寫的方法, 可以查看Object的equals方法注釋, 對equals有幾個性質(zhì)的要求: 當(dāng)我們要覆寫的類中某些值可能為null的時候,就需要對null做很多判斷和分支處理。 使用Guava的Objects.equal方法可以避免這個問題, 使得equals的方法的覆寫變得更加容易, 而且可讀性強,簡潔優(yōu)雅。 import org.junit.Test; import com.google.common.base.Objects; public class ObjectTest { @Test public void equalTest() { System.out.println(Objects.equal("a", "a")); System.out.println(Objects.equal(null, "a")); System.out.println(Objects.equal("a", null)); System.out.println(Objects.equal(null, null)); } @Test public void equalPersonTest() { System.out.println(Objects.equal(new Person("peida",23), new Person("peida",23))); Person person=new Person("peida",23); System.out.println(Objects.equal(person,person)); } } class Person { public String name; public int age; Person(String name, int age) { this.name = name; this.age = age; } } 運行輸出: true false false true false true hashCode方法: 當(dāng)覆寫(override)了equals()方法之后,必須也覆寫hashCode()方法,反之亦然。
這個方法返回一個整型值(hash code value),如果兩個對象被equals()方法判斷為相等,那么它們就應(yīng)該擁有同樣的hash
code。Object類的hashCode()方法為不同的對象返回不同的值,Object類的hashCode值表示的是對象的地址。
import org.junit.Test; import com.google.common.base.Objects; public class ObjectTest { @Test public void hashcodeTest() { System.out.println(Objects.hashCode("a")); System.out.println(Objects.hashCode("a")); System.out.println(Objects.hashCode("a","b")); System.out.println(Objects.hashCode("b","a")); System.out.println(Objects.hashCode("a","b","c")); Person person=new Person("peida",23); System.out.println(Objects.hashCode(person)); System.out.println(Objects.hashCode(person)); } } class Person { public String name; public int age; Person(String name, int age) { this.name = name; this.age = age; } } 128 4066 4096 126145 19313256 19313256 toString()方法: 因為每個類都直接或間接地繼承自O(shè)bject,因此每個類都有toString()方法。這個方法是用得最多的, 覆寫得最多, 一個好的toString方法對于調(diào)試來說是非常重要的, 但是寫起來確實很不爽。Guava也提供了toString()方法。
import org.junit.Test; import com.google.common.base.Objects; public class ObjectTest { @Test public void toStringTest() { System.out.println(Objects.toStringHelper(this).add("x", 1).toString()); System.out.println(Objects.toStringHelper(Person.class).add("x", 1).toString()); Person person=new Person("peida",23); String result = Objects.toStringHelper(Person.class) .add("name", person.name) .add("age", person.age).toString(); System.out.print(result); } } class Person { public String name; public int age; Person(String name, int age) { this.name = name; this.age = age; } } //============輸出=============== ObjectTest{x=1} Person{x=1} Person{name=peida, age=23} compare/compareTo方法: CompareTo:compareTo(Object
o)方法是java.lang.Comparable<T>接口中的方法,當(dāng)需要對某個類的對象進行排序時,該類需要實現(xiàn)
Comparable<T>接口的,必須重寫public int compareTo(T
o)方法。java規(guī)定,若a,b是兩個對象,當(dāng)a.compareTo(b)>0時,則a大于b,a.compareTo(b)<0
時,a<b,即規(guī)定對象的比較大小的規(guī)則; compareTo方法的通用約定與equals類似:將本對象與指定的對象停止比擬,如果本對象小于、等于、或大于指定對象,則分離返回正數(shù)、零、或正數(shù)。如果指定的對象類型無法與本對象停止比擬,則跑出ClassCastException。 下面我們簡單自己實現(xiàn)一個類的compareTo方法: import org.junit.Test; public class ObjectTest { @Test public void compareTest(){ Person person=new Person("peida",23); Person person1=new Person("aida",25); Person person2=new Person("aida",25); Person person3=new Person("aida",26); Person person4=new Person("peida",26); System.out.println(person.compareTo(person1)); System.out.println(person1.compareTo(person2)); System.out.println(person1.compareTo(person3)); System.out.println(person.compareTo(person4)); System.out.println(person4.compareTo(person)); } } class Person implements Comparable<Person>{ public String name; public int age; Person(String name, int age) { this.name = name; this.age = age; } @Override public int compareTo(Person other) { int cmpName = name.compareTo(other.name); if (cmpName != 0) { return cmpName; } if(age>other.age){ return 1; } else if(age<other.age){ return -1; } return 0; } } //========輸出=========== 上面的compareTo方法,代碼看上去并不是十分優(yōu)雅,如果實體屬性很多,數(shù)據(jù)類型豐富,代碼可讀性將會很差。在guava里, 對所有原始類型都提供了比較的工具函數(shù)來避免這個麻煩. 比如對Integer, 可以用Ints.compare()。利用guava的原始類型的compare,我們對上面的方法做一個簡化,實現(xiàn)compare方法: class PersonComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { int result = p1.name.compareTo(p2.name); if (result != 0) { return result; } return Ints.compare(p1.age, p2.age); } } 上面的代碼看上去簡單了一點,但還是不那么優(yōu)雅簡單,對此, guava有一個相當(dāng)聰明的解決辦法, 提供了ComparisonChain: class Student implements Comparable<Student>{ public String name; public int age; public int score; Student(String name, int age,int score) { this.name = name; this.age = age; this.score=score; } @Override public int compareTo(Student other) { return ComparisonChain.start() .compare(name, other.name) .compare(age, other.age) .compare(score, other.score, Ordering.natural().nullsLast()) .result(); } } class StudentComparator implements Comparator<Student> { @Override public int compare(Student s1, Student s2) { return ComparisonChain.start() .compare(s1.name, s2.name) .compare(s1.age, s2.age) .compare(s1.score, s2.score) .result(); } } } ComparisonChain是一個lazy的比較過程, 當(dāng)比較結(jié)果為0的時候, 即相等的時候, 會繼續(xù)比較下去, 出現(xiàn)非0的情況, 就會忽略后面的比較。ComparisonChain實現(xiàn)的compare和compareTo在代碼可讀性和性能上都有很大的提高。 下面來一個綜合應(yīng)用實例: import java.util.Comparator; import org.junit.Test; import com.google.common.base.Objects; import com.google.common.collect.ComparisonChain; import com.google.common.collect.Ordering; public class ObjectTest { @Test public void StudentTest(){ Student student=new Student("peida",23,80); Student student1=new Student("aida",23,36); Student student2=new Student("jerry",24,90); Student student3=new Student("peida",23,80); System.out.println("==========equals==========="); System.out.println(student.equals(student2)); System.out.println(student.equals(student1)); System.out.println(student.equals(student3)); System.out.println("==========hashCode==========="); System.out.println(student.hashCode()); System.out.println(student1.hashCode()); System.out.println(student3.hashCode()); System.out.println(student2.hashCode()); System.out.println("==========toString==========="); System.out.println(student.toString()); System.out.println(student1.toString()); System.out.println(student2.toString()); System.out.println(student3.toString()); System.out.println("==========compareTo==========="); System.out.println(student.compareTo(student1)); System.out.println(student.compareTo(student2)); System.out.println(student2.compareTo(student1)); System.out.println(student2.compareTo(student)); } } class Student implements Comparable<Student>{ public String name; public int age; public int score; Student(String name, int age,int score) { this.name = name; this.age = age; this.score=score; } @Override public int hashCode() { return Objects.hashCode(name, age); } @Override public boolean equals(Object obj) { if (obj instanceof Student) { Student that = (Student) obj; return Objects.equal(name, that.name) && Objects.equal(age, that.age) && Objects.equal(score, that.score); } return false; } @Override public String toString() { return Objects.toStringHelper(this) .addValue(name) .addValue(age) .addValue(score) .toString(); } @Override public int compareTo(Student other) { return ComparisonChain.start() .compare(name, other.name) .compare(age, other.age) .compare(score, other.score, Ordering.natural().nullsLast()) .result(); } } class StudentComparator implements Comparator<Student> { @Override public int compare(Student s1, Student s2) { return ComparisonChain.start() .compare(s1.name, s2.name) .compare(s1.age, s2.age) .compare(s1.score, s2.score) .result(); } } //=============運行輸出=========================== ==========equals=========== false false true ==========hashCode=========== -991998617 92809683 -991998617 -1163491205 ==========toString=========== Student{peida, 23, 80} Student{aida, 23, 36} Student{jerry, 24, 90} Student{peida, 23, 80} ==========compareTo=========== 1 1 1 -1 |
|