HashSet、hashcoede()、equals()之间的关系java
当用到散列表时,”hashCode() 和 equals() ”是有关系的!ide
例如:Hashset的插入的判断顺序是:先判断hashcode,不相同则插入;相同则继续比较equals是否为true,若是为true则表示两个对象相等,不能插入;若是是false则会散列到其余位置。this
总结:code
equals=true =》hashcode()相同 、反之不行对象
若是要使用散列表而且重写了equals方法就必定要重写hashcode()方法,以保证相同的对象不能同时加入HashSet中。get
为何重写equals方法必定要重写hashcode方法?hash
先看String
类重写的这两个方法class
public boolean equals(Object anObject) { //判断地址是否同样、同样则直接返回 if (this == anObject) { return true; } //判断对象是否属于String类 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; } public int hashCode() { //进行hash计算 int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
如今来看本身写的类(要求 id和name 相同则视为同一个对象)
一、先看自动生成的者两个方法
默认生成的比较了book类的全部参数,以及进行了哈希运算。方法
class Book1 { int id; String name; String author; double price; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Book1 book1 = (Book1) o; return id == book1.id && Double.compare(book1.price, price) == 0 && Objects.equals(name, book1.name) && Objects.equals(author, book1.author); } @Override public int hashCode() { return Objects.hash(id, name, author, price); } }
二、要求是di和name相同则视为同一本书、即同一对象,相同的对象不能加入到散列表中,只须要比较id和name,改写以下总结
/** * 重写equals方法比较id和name * @param o * @return */ @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Book1 book1 = (Book1) o; return id == book1.id && Objects.equals(name, book1.name); } /** * 重写equals要重写hashcode set加入时会先判断hashcode是否相等,再判断是否equals * 只有hashcode相同 和equals 同时成立 才能保证set的全部元素都不相等 * @return */ @Override public int hashCode() { return Objects.hash(id, name); }
若是只是改写了equals方法 hashcode方法默认仍是进行四个参数的哈希运算,计算出的两个对象的若是id和name相同,author或者price不一样也会计算出不一样的hashcode。这样的话咱们自定义的两个相同的对象都能成功加入hashset,违背原则,因此必须同时覆盖这两个方法。
Book1 b1 = new Book1(1, "hh", "zs", 122.0); Book1 b2 = new Book1(1, "hh", "zh", 112.0);
这两个对象只能加进去一个到HashSet中