Set接口 [Collection】的子类
HashSet
特点【无序,不可重复,不能排序】
默认比较地址值【地址相同的值相同】,重写后可比较内容【内容相同的值相同】
1.比较地址值【默认】
public class Demo1 {
public static void main(String[] args) {
HashSet<Student> hs = new HashSet<>();
Student s1 = new Student("张三", 18);
Student s2 = new Student("李四", 18);
Student s3 = new Student("张三", 18);
System.out.println("s1:"+ s1.hashCode());
System.out.println("s2:"+ s2.hashCode());
System.out.println("s3:"+ s3.hashCode());
System.out.println("s1:"+ s1.hashCode());
hs.add(s1);
hs.add(s2);
hs.add(s3);
for(Student student : hs){
System.out.println(student);
}
}
}
打印结果:
--------------------------------------------------------------
s1:189568618
s2:960604060
s3:1349393271
s1:189568618
Student{name='张三', age=18}
Student{name='张三', age=18}
Student{name='李四', age=18}
2.而默认比较地址值不能达到我们实际的要求,则需要重写HashaCode方法使其比较属性值
【API中有一些类已经重写了HashaCode,给出了比较规则,如:String:数值大小、字符串长度 ]
public class Demo1 {
public static void main(String[] args) {
HashSet<String> hs = new HashSet<>();
hs.add("hello");
hs.add("world");
hs.add("java");
hs.add("java");
hs.add("java");
for (String h : hs) {
System.out.println(h);
}
}
}
打印结果:
--------------------------------------------------------------
world
java
hello
【未重写的类,如:我们自定义的类,则需要去类中重写HashC ode方法】
public class Demo1 {
public static void main(String[] args) {
HashSet<Student1> hs = new HashSet<>();
Student1 s1 = new Student1("张三", 18);
Student1 s2 = new Student1("李四", 18);
Student1 s3 = new Student1("张三", 18);
hs.add(s1);
hs.add(s2);
hs.add(s3);
for(Student1 student : hs){
System.out.println(student);
}
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return Objects.equals(name, student.name);
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
打印结果:
------------------------------------------------------------
Student{name='张三', age=18}
Student{name='李四', age=18}
3.底层原理【链表,数组,[链表满8为]红黑树】
计算哈希值 : 根据元素的哈希数和数组的长度取余得到存入的位置 如:21501220%16
注:两种Set实现类的选择:【如果你需要得到一个有序的结果时就应该使用TreeMap(因为HashMap中元素的排列顺序是不固定的)。除此之外,由于HashMap有更好的性能,所以大多不需要排序的时候我们会使用HashMap】