1.Set是Collection子接口
模拟了数学上的集的概念。
-----------------------------------------------------------------------Set集合存储特点:
1):不允许元素重复.
2):不会记录元素的先后添加顺序.
-----------------------------------------------------------------------
Set只包含从Collection继承的方法,不过Set无法记住添加的顺序,不允许包含重复的元素。当试图添加两个相同元素进Set集合,添加操作失败,add()方法返回false。
import java.util.HashSet;
import java.util.Set;
public class SetDemo2 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("小明");
set.add("小红");
set.add("小张");
set.add("小明");//和第一个是同一个对象,所以不能添加
System.out.println(set.size());//3
System.out.println(set);//打印结果:[小张, 小明, 小红],不会记录添加顺序
}
}
Set判断两个对象是否相等用equals,而不是使用==。也就是说两个对象equals比较返回true,Set集合是不会接受这个对象的。
HashSet是Set接口最常用的实现类,顾名思义,底层才用了哈希表(散列/hash)算法.
其底层其实也是一个数组,存在的意义是提供查询速度,插入速度也比较快,但是适用于少量数据的插入操作.
HashSet类是线程不安全的类,在多线程环境下想要保证线程安全.
HashSet set = Collections.synchronizedSet(new HashSet(...));
在HashSet中如何判断两个对象是否相同问题:
1):两个对象的equals比较相等. 返回true,则说明是相同对象.
2):两个对象的hashCode方法返回值相等.
对象的hashCode值决定了在哈希表中的存储位置.
二者:缺一不可.
当往HashSet集合中添加新的对象的时候,先回判断该对象和集合对象中的hashCode值:
1):不等: 直接把该新的对象存储到hashCode指定的位置.
2):相等: 再继续判断新对象和集合对象中的equals做比较.
1>:hashCode相同,equals为true: 则视为是同一个对象,则不保存在哈希表中.
1>:hashCode相同,equals为false:非常麻烦,存储在之前对象同槽为的链表上(拒绝,操作比较麻烦).
对象的hashCode和equals方法的重要性:
每一个存储到hash表中的对象,都得提供hashCode和equals方法,用来判断是否是同一个对象.
存储在哈希表中的对象,都应该覆盖equals方法和hashCode方法,并且保证equals相等的时候,hashCode也应该相等.通过源码可以看到,String类,Integer等8大基本类型包装类都已经覆盖equals方法和hashCode方法,有了自己的判断方式,所以可以直接使用.
如果需要把我们自定义的对象存储到哈希表中,该类型的对象应该覆盖equals和hashCode方法,并在该方法中提供自己的判断规则.可以使用Eclipse工具自动生成hashCode和equals方法.
生成之后就是下面这样:
class Person{
private int id;
private int age;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (id != other.id)
return false;
return true;
}
}
你可以根据自己的需求来选择判断的条件
举个例子:我们就根据id来决定Person是同一个对象,根据上面的步骤生成根据id来判断的hashCode和equals方法,然后测试添加,注意,Set集合是根据这两个方法一起来判断的,缺一不可
import java.util.HashSet;
import java.util.Set;
//Person类
class Person{
private int id;
private int age;
private String name;
public Person() {
super();
}
public Person(int id, int age, String name) {
super();
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";
}
//hashCode方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
//equals方法
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (id != other.id)
return false;
return true;
}
}
//测试类
public class SetDemo1 {
public static void main(String[] args) {
Person p1 = new Person(0, 18, "张三");
Person p2 = new Person(1, 18, "李四");//与p1相比年龄相同,姓名,id不同
Person p3 = new Person(2, 19, "张三");//与p1相比姓名相同,年龄,id不同
Person p4 = new Person(3, 18, "张三");//与p1相比年龄和姓名都相同,但是id不同
Person p5 = new Person(0, 19, "王五");//与p1相比id相同,只要id相同就是同一个对象,上面我们已经定义了
Set<Person> set = new HashSet<>();
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
set.add(p5);//添加失败,因为是同一个对象
System.out.println(set.size());//只添加了4个,因为第5个和第一个相同
System.out.println(set);//打印结果[Person [id=3, age=18, name=张三], Person [id=1, age=18, name=李四], Person [id=2, age=19, name=张三], Person [id=0, age=18, name=张三]]
//可以看到打印结果跟添加顺序不一样,说明Set集合不会记录添加顺序
}
}
对象的hashCode计算公式