什么是set
Set 具有与 Collection 完全一样的接口 行为上不同 Set 不保存重复的元素
分类
- HashSet:最主要的实现类 线程不安全 可以存储null
- LinkedHashSet:作为HashSet子类 遍历内部数据时 可以按照添加的方式来显示
- TreeSet:可以按照添加对象的指定属性 进行排序
Set特点
- 无序:存储的数据在底层中并非按照数据的索引 而是根据数据的哈希值来确定位置
- 不可重复:保证添加的元素按照equals判断时 不能返回true 即相同的元素只能添加一个
- Set接口中没有拓展Collection中的方法(
- 向Set接口中添加数据时 其所在的类一定要重写 hashCode() 和 equals()方法 相等的对象必须拥有相等的散列码
HashSet添加元素过程
向HashSet添加 元素 a 首先调用a所在类的hashCode()方法 计算a的哈希值
此哈希值通过HashSet内部某种算法计算出 a 在HashSet中的位置(即为 索引位置)
判断此位置上是否有值
如果没有 元素 a 添加成功 ==>情况1
如果存在元素 b(或者以链表存在的多个元素) 则比较元素 a 和 元素 b 的hash值
如果不相同 添加成功 ==>情况2
如果相同 调用元素 a 所在类的equals方法
equals返回true 添加失败
equals返回false 添加成功 =>情况3
情况2和情况3 元素 a 和 已经存在指定索引位置的元素以链表的方式进行存储
jdk8:原来的数据在数组中 指向元素 a
jdk7:a放到数组中 指向原来的数据
HashSet底层: 数组 + 链表
示例
HashSet
package com.collection;
import org.junit.Test;
import java.util.HashSet;
import java.util.Set;
/*
* Set接口
* 无序 不可重复
* 无序:存储的数据在底层中并非按照数据的索引 而是根据数据的哈希值来确定位置
* 不可重复:保证添加的元素按照equals判断时 不能返回true 即相同的元素只能添加一个
* Set接口中没有拓展Collection中的方法
* */
public class Demo03 {
@Test
public void test(){
Set set = new HashSet();
set.add(111);
set.add(222);
set.add(333);
set.add(111);
set.add(new User("yyll",20));
set.add(new User("yyll",20));
System.out.println(set);
/*
* 输出结果 [333, 222, 111]
* 不可重复
* */
}
}
TreeSet
package com.collection;
import org.junit.Test;
import java.util.TreeSet;
public class Demo04 {
@Test
public void test(){
TreeSet treeSet = new TreeSet();
treeSet.add(123);
treeSet.add(445);
treeSet.add(1323);
treeSet.add("bb");
/*
* java.lang.Integer cannot be cast to java.lang.String
*
* 不能添加不同类型的数据
* TreeSet
* */
}
}
小结
- Set接口
无序
不可重复
-
TreeSet
不能添加不同类型的数据 可以自定义排序规则