Set集合
- 无序,没有索引,添加和取出的顺序不一样
- 不允许重复元素,最多包含一个null
- 常用方法和Collection接口一样
- 不能通过索引方式来获取元素
- 循环遍历:增强for循环,迭代,不能使用普通for循环,没有get方法
1.迭代遍历:
Set set = new HashSet();
Iterator it = set.iterator();
while (it.hasNext()) {
String str = it.next(); System.out.println(str);
}
2.for循环遍历:
for (String str : set) {
System.out.println(str);
}
Set的继承结构图
hashSet的理解
源码分析见: 详情debug调试hashSet底层
底层是hashmap,hashmap的结构是:数组+链表+红黑树的结构
public HashSet() {
map = new HashMap<>();
}
HashSet的添加操作
package JavaTest;
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
System.out.println(hashSet.add(new String("lzq")));
// 添加失败,有线程池的原因
System.out.println(hashSet.add(new String("lzq")));
System.out.println(hashSet.add(new DogA("旺财"))); // 添加成功
System.out.println(hashSet.add(new DogA("旺财"))); // 添加成功
System.out.println(hashSet);
}
}
class DogA{
public String name ;
public DogA(String name) {
this.name = name;
}
}
HashSet底层原理总结
- HashSet底层是HashMap
- 添加一个元素时,先得到hash值,会转成->索引值
- 找到出处数据table表,看这个索引位置是否已经存放元素
- 如果没有,直接加入
- 如果有,调用equals方法进行比较,如果相同就放弃添加,如果不相同则添加到最后
- 在Java8中,如果一条链表的元素个数达到TREEIFY_THRESHOLD(默认为8) , 并且 table大小>=MIN_TREEIFY_CAPACITY(默认为64),就会进行红黑树化
LinkedHashSet的理解
-
LinkedHashSet是HashSet的子类
public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, java.io.Serializable { -
LinkedHashSet底层是一个LinkedHashMap,底层维护了一个table数组+双链表
-
LinkedHashSet根据元素的hashcode值来决定元素的存储位置, 同时使用了链表维护元素的次序,是的元素看起来是插入顺序保存的
-
LinkedHashSet不允许添加重复元素,可以保证元素的有序性
-
每一个节点有before和after属性,这样可以形成双向链表
-
在添加一个元素时,先求hash值,再求索引,确定该元素在table的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加)
-
第一次添加时,将数组直接扩容为16,存放的结点类型为LinkedhashMap&Entry (多态数组)数组是HashMapEntry类型
-
示意图