set系列集合
-
无序:存取顺序不一致
-
不重复:可以去除重复
-
无索引:没有带索引的方法,所以不能使用普通的for循环,也不能通过索引来获取元素
set集合的实现类
-
HashSet:无序、不重复、无索引
-
LinkedHashSet:有序、不重复、无索引
-
TreeSet:可排序、不重复、无索引
set接口中的方法基本与Collection的API一致。
package MyApi.mySet;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Consumer;public class a01setDemo01 {public static void main(String[] args) {//1.创建一个set集合对象Set<String> s=new HashSet<>();//2.添加元素boolean b1 = s.add("张三");boolean b2 = s.add("李四");boolean b3= s.add("王五");//3.打印集合// System.out.println(s);//迭代器遍历/* Iterator<String> it = s.iterator();while(it.hasNext()){String next = it.next();System.out.println(next);}*///增强for遍历/*for (String s1 : s) {System.out.println(s1);}*///Lambda表达式s.forEach( str ->System.out.println(str));}
}
HashSet
HashSet底层原理
-
HashSet集合底层采取哈希表存储数据
-
哈希表是一种对于增删改查数据性能都较好的结构
哈希表组成
-
Jdk8之前:数组+链表
-
Jdk8:数组+链表+红黑树
哈希值
-
根据hasHcode方法计算出来的int类型的整数
-
该方法定义在Oject类中,所有对象都可以调用,默认使用地址值进行计算
-
一般情况下,会重写hashCode方法,利用内部对象属性值计算哈希值
对象的哈希值特点
-
如果没有重写hashCode方法,不同对象计算出来的哈希值是不同的
-
如果已经重写hashCode方法,不同的对象只要属性值相同,计算出来的哈希值就是 一样的
-
在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)
HashSet JDK8以前底层原理、
-
创建一个默认长度16,默认加载因为0.75的数组,数组名为table
-
根据元素的哈希值根数组的长度计算出应存入的位置
-
判断当前位置是否为null,如果是Null直接存入
-
如果位置不为null,表示有元素,则调用equals方法比价属性值
-
一样:不存 不一样:存入数组,形成链表
jdk8以前:新元素存入数组,老元素挂在新元素下面
JDK8以后:新元素直接挂在老元素下面
JDK8以后,当链表的长度超过八而且数组长度大于等于64时,自动转换为红黑树
如果集合中存储的是自定义对象,必须要重写equals和hashCode方法
LinkedHashSet底层原理
-
有序、不重复、无索引
-
这里的有序是指保证存储和取出来的元素顺序一致
-
原理:底层数据结构依然是哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
TreeSet
-
不重复、无索引、可排序
-
可排序:按照元素的默认规则(从小到大)排序
-
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
package MyApi.mySet;import java.util.Iterator;
import java.util.TreeSet;
import java.util.function.Consumer;public class TreeSetDemo1 {public static void main(String[] args) {TreeSet<Integer> ts=new TreeSet<>();ts.add(4);ts.add(5);ts.add(1);ts.add(3);ts.add(2);
//打印集合System.out.println(ts);//遍历集合Iterator<Integer> iterator = ts.iterator();
while(iterator.hasNext()){Integer next = iterator.next();System.out.println(next);}System.out.println("------");for (Integer t : ts) {System.out.println(t);}System.out.println("------");ts.forEach(integer-> System.out.println(integer));}
}
TreeSet集合默认的规则
-
对于数值类型:Integer、Double,按照从小到大的顺序进行排序。
-
对于字符、字符串类型:按照字符在ASCII码表中的数字升序进行排序。