HashSet
-
没有下标,不能存放重复元素
-
初始容量为16,负载因子0.75,到容量被用到0.75 = 3/4的时候自动扩容
-
底层结构是哈希表
-
增删元素速度快,但相对的,占用的空间大
-
元素不能重复,并且无序
-
存储方式是散列存储
当存储一个元素的时候,它先判断它的hashcode和集合里面的元素的hashcode是否相等,如果不相等,则存放在类似数组结构的table里面,但存放的并不是元素,而是元素的哈希码。当哈希码相等时,再通过equals方法判断元素的内容是否相等,不相等就串再头部的下面,类似链表结构。当相等时,则覆盖原内容。所以说它的占用的空间比较大。
HashSet每次添加对象时,判断对象是否在集合中重复,主要依赖于对象的"哈希码"。
每个对象都有一个"哈希码",可以通过Object的hashCode方法获得
Object的hashCode默认返回的是对象的内存地址
用哈希算法来判断元素是否重复,可以减少判断次数
对象的hashCode应该根据属性值计算,这样具有相同属性值的对象的hashCode就是一致的,然而具有不同的属性值的对象也有可能有相同的哈希码,所以哈希码相同时还要比较属性值。
比较两元素是否相等,当元素是对象的时候,需要比较它们的哈希码和equals方法,需要重写hashCode和equals方法。
package Demo8;
import java.util.HashSet;
public class Student {
private String name;
private int age;
private String address;
public Student() {
super();
}
public Student(String name, int age, String address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", address=" + address + "]";
}
@Override
public int hashCode() {
String str = this.name+this.age;
return str.hashCode();
}
@Override
public boolean equals(Object obj) {
Student student = new Student();
if(obj instanceof Student) {
student = (Student)obj;
}
if(this.name != student.getName()) {
return false;
}
if(this.age != student.getAge()) {
return false;
}
return true;
}
}
当它们的对象相同时,内容不同时
Student stu1 = new Student("aaa",12,"mm");
Student stu2 = new Student("aaa",12,"cc");
HashSet hs = new HashSet();
hs.add(stu1);
hs.add(stu2);
System.out.println(hs);
//结果为[Stuent [name=aaa, age=12, address=cc], Student [name=aaa, age=112, address=mm]]
当它们的对象相同时,内容相同时
Student stu1 = new Student("aaa",12,"mm");
Student stu2 = new Student("aaa",12,"mm");
HashSet hs = new HashSet();
hs.add(stu1);
hs.add(stu2);
System.out.println(hs);//结果为[Student [name=aaa, age=12, address=mm]]
当它们的对象不同时,则表示的是不同元素
TreeSet
排序集合
-
底层结构是二叉树
-
不能存放重复元素
-
能自动排序
TreeSet集合判断新元素是否重复,不是利用equals判断,而是利用compareTo方法判断,如果compareTo返回0,则表示重复
如果需要判断集合中的对象的值是否相等,并且排序,则需要重写compareTo方法。而重写compareTo方法又必须要实现Comparable接口
package Demo8;
import java.util.Set;
import java.util.TreeSet;
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 int compareTo(Person o) {
if (this.age > o.getAge()) {
return 1;
} else if (this.age < o.getAge()) {
return -1;
} else {
if (this.name.hashCode() > o.getName().hashCode()) {
return 1;
} else if (this.name.hashCode() < o.getName().hashCode()) {
return -1;
}else {
return 0;
}
}
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public static void main(String[] args) {
Set<Person> ts = new TreeSet();
ts.add(new Person("aa", 19));
ts.add(new Person("bb", 17));
ts.add(new Person("bb", 17));
ts.add(new Person("aa", 19));
System.out.println(ts);
//结果为[Person [name=bb, age=17], Person [name=aa, age=19]]
}
}
可以看到,当重写compareTo方法后,TreeSet会自动帮我们排序,并且去掉了重复的元素
返回值为1的时候,则传入的元素在比较是的元素的前面,-1在后面。0则相等
-
TreeSet的第二种比较方式,当元素自身不具备可比较性时(不能实现Comparable接口),这时需要让集合自己具备可比较性。
-
在集合初始化时,可以指明集合的比较方式。
-
当两种比较方式都存在时(实现Comparable接口和比较器),以比较强为主。
让集合具备可比较性(使用比较器),需要在初始化时创建Comparator对象:
package Demo8;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 int compareTo(Person o) {
if (this.age > o.getAge()) {
return 1;
} else if (this.age < o.getAge()) {
return -1;
} else {
if (this.name.hashCode() > o.getName().hashCode()) {
return 1;
} else if (this.name.hashCode() < o.getName().hashCode()) {
return -1;
} else {
return 0;
}
}
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public static void main(String[] args) {
// Set<Person> ts = new TreeSet();
// ts.add(new Person("aa", 19));
// ts.add(new Person("bb", 17));
// ts.add(new Person("bb", 17));
// ts.add(new Person("aa", 19));
// System.out.println(ts);
Set<Person> ts1 = new TreeSet(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
if (o1.getAge() > o2.getAge()) {
return 1;
} else if (o1.getAge() < o2.getAge()) {
return -1;
} else {
if (o1.getName().hashCode() > o2.getName().hashCode()) {
return 1;
} else if (o1.getName().hashCode() < o2.getName().hashCode()) {
return -1;
} else {
return 0;
}
}
}
});
ts1.add(new Person("aa", 19));
ts1.add(new Person("bb", 17));
ts1.add(new Person("bb", 17));
ts1.add(new Person("aa", 19));
System.out.println(ts1);
//结果为[Person [name=bb, age=17], Person [name=aa, age=19]]
}
}