HashTree:底层数据结构是:哈希表,线程不安全(其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75,如果对于迭代性能要求比较高,对加载因子设置降低或者默认),通过hashCode方法和equals方法来保证元素的唯一性。
/** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<E,Object>(); }
比较原理:先判断类中的属性各个hashcode 计算的值,如hashcode值相同才会去判断equals,否则,是不会调用equals方法的。
根据以上原理得知,我们必须要重写hashcode()和equals()方法,
import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Student { private static final long serialVersionUID = 1L; private String id; private String name; private int age; public Student(String id, String name, int age) { super(); this.id = id; this.name = name; this.age = age; } public Student() { super(); // TODO Auto-generated constructor stub } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } @Override public int hashCode() { final int prime = 31;// 为什么是31,可以思考一下,到时再整理出来 int result = 1; result = prime * result + age; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); System.out.println("hashCode method :" + result); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) { return true; } if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public static void main(String[] args) { Set<Student> set = new HashSet<Student>(); Student student1 = new Student("1", "Tom", 16); Student student2 = new Student("2", "Lucy", 13); Student student2_1 = new Student("2", "Lucy", 13); Student student3 = new Student("3", "Peter", 14); set.add(student1); set.add(student2); set.add(student2_1); set.add(student3); Iterator<Student> iterator = set.iterator(); while (iterator.hasNext()) { Student next = iterator.next(); System.out.println(next.getName() + " :" + next.getAge()); } } }
同样contains(obj)方法中,也对比顺序是 hashCode 和equals(o) 代码如下
/** * Returns the entry associated with the specified key in the * HashMap. Returns null if the HashMap contains no mapping * for the key. */ final Entry<K,V> getEntry(Object key) { int hash = (key == null) ? 0 : hash(key.hashCode()); for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; }