HashSet是Set接口的实现类,其底层数据结构为哈希表。
HashSet是线程不安全的(不保证同步)。
HashSet优点:添加、删除、查询效率高。
缺点:无序
哈希表的工作原理:
首先,拿到元素,计算元素的HashCode值,使用根据y=K(x)的哈希函数计算出元素的存储位置,如果该位置没有元素,则将元素存放到该位置。如果该位置上已经存在元素,则使用equals方法比较元素的内容是否相同,如果相同,则不再添加进去,摒弃掉。如果不同,则在同一个位置拉链一个空间放置该元素。
注意1:y代表存储位置,x代表hashCode值,即哈希码,y=K(x)的作用是根据哈希码去计算存储位置。
注意2:Integer类型对象的哈希码就是对象的数值本身。
注意3:HashSet是无序的,元素是唯一的。
添加自定义对象:
如果要向HashSet中存储元素时,元素对象中一定要实现hashCode方法和equals方法,不然会运行报错。因为根据哈希表原理,存储时要使用hashCode方法和equals方法进行判断存储的位置。
1 package cn.sxt03.hashset; 2 3 public class Student { 4 private String id; 5 private String name; 6 private int age; 7 8 // … 9 10 11 @Override12 public int hashCode() {13 final int prime = 31;14 int result = 1;15 result = prime * result + age;16 result = prime * result + ((id == null) ? 0 : id.hashCode());17 result = prime * result + ((name == null) ? 0 : name.hashCode());18 return result;19 }20 21 @Override22 public boolean equals(Object obj) {23 if (this == obj)24 return true;25 if (obj == null)26 return false;27 if (getClass() != obj.getClass())28 return false;29 Student other = (Student) obj;30 if (age != other.age)31 return false;32 if (id == null) {33 if (other.id != null)34 return false;35 } else if (!id.equals(other.id))36 return false;37 if (name == null) {38 if (other.name != null)39 return false;40 } else if (!name.equals(other.name))41 return false;42 return true;43 }44 45 @Override46 public String toString() {47 return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";48 }49 50 }