咱們很方便的定義一個java POJO類,用來表示一個複雜對象。這個對象可能包含一些基本類型的數據成員。好比下面的例子: java
public class Info { public String uri; public String name; public int id; public Info(String uri, String name, int id) { this.uri = uri; this.name = name; this.id = id; } }
接下來,咱們有可能會把這種對象存儲在List或者Map裏面,來方便使用。 ide
List<Info> lists = getInfos();
接下來,有人就會這樣使用這個List: this
Info info = new Info("xxx", "yyy", 1); lists.remove(info);
運氣很差,移交給QA以後,問題出現了,info對象還在。 code
這個問題說開了一點都不復雜,可是在一個複雜的系統中由於這樣的小問題致使出現的bug,排查起來很讓人煩心。 對象
拋開原理不談,咱們就看看java ArrayList是怎麼實現remove(Object obj)。 element
public boolean More ...remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false;
裏面清楚的寫着:o.equals(elementData[index])。 rem
Info對象沒有實現equals和hashCode。 get
按照java的標準寫法,equals和hashCode要寫不少代碼。這裏咱們用Guava來簡化這個工做。 hash
public class Info { public String uri; public String name; public int id; public Info(String uri, String name, int id) { this.uri = uri; this.name = name; this.id = id; } @Override public int hashCode() { return Objects.hashCode(uri, name, id); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final Info other = (Info) obj; return Objects.equal(this.uri, other.uri) && Objects.equal(this.name, other.name) && Objects.equal(this.id, other.id); } }
簡單多了。 ast