Vector底层结构和源码剖析
Vector底层结构和ArrayList的比较
查看源码和上一篇的差不多一样一样的,只不过扩容机制这里有点不一样。
就扩容了
双链表LinkedList
关于双链表的基础知识我以前做过笔记可以看一下mp.weixin.qq.com/s/fVGp6fJx2…
Set接口和常用方法和List Collection的一毛一样遍历方式也是
不能使用索引的方式来获取.
Set接口实现类- HashSet
HashSet底层机制说明(看源码)
分析HashSet的添加元素底层是如何实现
预留的一个安全空间
剩下的不看了,step out出去
这能看到给加进去了
HashSet set = new HashSet();
set.add("gjy");
set.add("php");
System.out.println(set);
/*
1 执行
public HashSet() {
map = new HashMap<>();
}
2 执行add()
public boolean add(E e) {// e="gjy"
return map.put(e, PRESENT)==null;
}
3 执行put() 该方法会执行hash(key) 得到key对应的hash值,算法h = key.hashCode()^(h >>> 16)
public V put(K key, V value) {//key = "gjy" value = PRESENT
return putVal(hash(key), key, value, false, true);
}
4 执行putVal
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;//这里定义了辅助变量
//tabLe 就是HashMap 的一个数组,类型是Node []
if ((tab = table) == null || (n = tab.length) == 0)//if语句表示如果当前table是null,或者大小=0
n = (tab = resize()).length; //就是第一次扩容,到16个空间。
//根据key,得到hash去计算该key应该存放到tabLe表的哪个索引位置
if ((p = tab[i = (n - 1) & hash]) == null) //并把这个位置的对象,赋给p
//(2)判断p是否为null
//(2.1) 如果p为null, 表示还没有存放元素,就创建一个Node (key = "gjy" value = PRESENT)
tab[i] = newNode(hash, key, value, null);//(2.2) 就放在该位置
else {//一个开发技巧提示:在需要局部变量(辅助变量)时候,在创建
Node<K,V> e; K k;
//如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样
//并且满足 下面两个条件之
if (p.hash == hash && //(1) 准备加入的key和p指向的Node结点的key 是同一个对象
((k = p.key) == key || (key != null && key.equals(k))))//(2) p指向的Node结点的key的equals()和准备加入的key比较后相同
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
还有好多分析不下去了
分析HashSet的扩容和转成红黑树机制
看源码
按照这样依次类推
链表元素到8个之后再加元素到这一条链表的话,数组会自动扩容,直到满足树化的条件
Set接口实现类- LinkedHashSet
后面的自己去看一下
练习题
定义一个Employee类,该类包含: private成员属性name,age要求: 1.创建3个Employee放入HashSet中 2.当name和age的值相同时,认为是相同员工,不能添加到HashSet集合中
...
public class hashset {
@SuppressWarnings({"all"})
public static void main(String[] args) {
HashSet set = new HashSet();
set.add(new Employee("yjg",54));
set.add(new Employee("htf",23));
set.add(new Employee("htf",23));//重写之前加入三个,重写之后这个加入不成功
System.out.println(set);
}
}
class Employee {
//属性
//构造器
//getter setter
//to String
//重写 alt+insert equals...
//如果name和age相同时,则返回相同的hash值
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return age == employee.age &&
Objects.equals(name, employee.name);
}
@Override
public int hashCode() {
//这可以追一下源码hash
return Objects.hash(name, age);
}
}
要使属性的值相同时不能加入到集合中就chong'xie重写equals就行(alt+insert)linkedlist一样