这里打算分析一下linkedHashSet的源码,也基本上把hashSet源码的方法实现过了一下,所以后面就不分析hashSet的源码了,其实这篇内容在我看来也仅仅帮助需要的人可以快速了解一下set方法的基本实现,但是并不详细,理解hashSet的使用场景以及linkedHashSet的业务场景就非常有必要了。
(1) //构造一个默认容量为16,负载因子为0.75的hashSet
public LinkedHashSet() {
super(16, .75f, true);
}
(2) //其实hashset以及linkedHashSet底层实现都是map实现的,那我们继续~
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
(3) //继续按照java继承的思路进行实现
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
(4) //接下来就是利用已经编写好的hashMap来实现了
public HashMap(int initialCapacity, float loadFactor) {
// 进行参数校验
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
// 进行容量的初始分配
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
// 校验负载因子是否正确
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
// 调用map的put()方法
public boolean add(E e) {
//PRESENT就是一个常量了,如果返回的结果不为null,表明map里面已经有了元素e,则添加失败
return map.put(e, PRESENT)==null;
}
// 由于底层实现是基于map实现,所以返回map中entry的数量就可以了
public int size() {
return map.size();
}
// 调用已有的size方法即可
public int size() {
return size;
}
/**
* The number of key-value mappings contained in this map.
*/
transient int size
// 其实size的注释说明已经很清晰的说明了它的含义
public boolean isEmpty() {
return map.isEmpty();
}
// 底层实现还是判断map中的key-value的数量是否为0
public boolean isEmpty() {
return size == 0;
}
public boolean contains(Object o) {
// 调用map的containsKey方法
return map.containsKey(o);
}
public boolean containsKey(Object key) {
// 判断map中是否存在key
//关于key的查询,主要还是基于hashMap的get方法实现,关于这部分内容,这里暂时不做分析,后面在继续分析了
//其实本质就是链表的查询或树节点数据的查询
return getNode(hash(key), key) != null;
}
// 调用map的clear方法,移除所有的键值对
public void clear() {
map.clear();
}
// 将每个元素都置为null,等待gc机制触发,将不可达对象进行回收
public void clear() {
Node<K,V>[] tab;
modCount++;
if ((tab = table) != null && size > 0) {
size = 0;
for (int i = 0; i < tab.length; ++i)
tab[i] = null;
}
}
其实,这里自己多次犹豫要不要写这篇文章出来,因为linkedHashSet底层实现是基于hashMap实现的,我虽然分析了hashTable的源码,但却没有分析hashMap的源码,如果一上来就分析linkedHashSet的源码,也仅仅对其基本的方法做个大致的理解,本质上还是没有什么变化,多次犹豫之后,我还是觉得先暂时分析一下吧,hashMap的源码太过复杂了,如果分析它,需要好长时间才能浅显的分析一下,那么我还是需要多看看它的实现才能按照自己的理解慢慢输出,所以这里就暂时分析了linkedHashSet源码。
其实,对于这篇文章,分析之后还是有一些收获的,比如说我们可以快速的理解set每个方法的作用,以及它的使用场景,对于开发还是比较好一点的。