set集合的特点是没有索引值,且元素不能重复。
判断两个元素是否重复:两个元素的哈希值&&(地址值是否相同 || equals方法结果)
即:先比较两个对象哈希值,如果哈希值不同,则两个元素不重复,如果哈希值相同,则继续比较地址值或equals方法,如果equals为true,则元素重复,如果为false则不重复。
以set集合中的hashset为例:
package Demo1;
import java.util.HashSet;
public class p10 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("小明");
set.add("小花");
set.add("小强");
set.add("小明");
set.add("小花");
System.out.println(set);
}
}
打印结果为:[小强, 小明, 小花],
代码中一共添加了五个元素,而集合中只有小强, 小明, 小花。
出现这样的结果的原因是:
1. HashSet<String> set = new HashSet<>();
通过这一步,我们创建了一个hashset的对象:实质上是在“堆”中开辟了一个空间:
首先我们知道hashset的底层结构是哈希表,在JDK1.8及以后,它由数组+链表/红黑树构成。
底层会创建一个默认长度为16的Object[],并将加载因子默认为0.75。
2. set.add("小明");
新增流程为:
a.计算新增元素的哈希值(通过hashcode方法获取)
b.用哈希值%数组长度,得到的余数作为新增元素的索引值;
c.如果该索引值位置没有元素,可直接新增;
如果该索引值位置有元素,用equals方法去比较两个元素是否相同。
计算字符串"小明"的哈希值,就会在集合中找有没有"小明"哈希值的元素,首次新增,可直接新增。就会将元素"小明"存储到集合中去。
3. set.add("小花");
set.add("小强");
set集合在调用add方法时,会调用元素的hashcode和equals方法,判断元素是否重复。计算字符串的哈希值,就会在集合中找有没有哈希值的元素,就会将元素存储到集合中去。
4. set.add("小明");
set.add("小花");
add方法会调用hashCode方法,计算字符串"小明"和"小花"的哈希值,在集合中找有没有这个哈希值的元素,发现有(哈希冲突),会调用equals方法和哈希值相同的元素进行比较,equals方法返回true,认定两个元素相同,就不会存储"小明"和"小花"到集合中。
这就是set元素存储元素不重复的元素的原理。但是这有一个前提,存储元素必须重写hashcode和eqluas方法,保证元素不重复。