集合源码
1.ArrayList
1.默认属性
private static final long serialVersionUID = 8683452581122892189L;
//默认的容量
private static final int DEFAULT_CAPACITY = 10;
//共享的空数组实例,供有参构造器使用,将其与无参构造器区分开来
private static final Object[] EMPTY_ELEMENTDATA = {};
//共享的空数组实例,供无参构造器使用,将其与其他构造器区分开来
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//用来存储数据的数组
//transient表示序列化时忽略改数组
transient Object[] elementData; // non-private to simplify nested class access
维护大小
private int size;
2.构造方法
//指定一初始化容量,创建一个长度指定的object集合
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//如果初始化长度为0复制给一个空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
//否否则就抛出异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//无参构造初始化一个空数组
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//传如一个集合
public ArrayList(Collection<? extends E> c) {
//先将集合转换为数组
Object[] a = c.toArray();
//如果集合的长度不为0
if ((size = a.length) != 0) {
//如果该集合是arrlist结合直接复制给子类.原因是因为有的有的集合tochar返回的不是ocject类型的数组
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// 否则就赋值给一个空的数字
elementData = EMPTY_ELEMENTDATA;
}
}
2.常用方法
1.add方法
//添加元素e
public boolean add(E e) {
//确认是否需要扩容
ensureCapacityInternal(size + 1); // size+1表示需要的最小长度
elementData[size++] = e;//进行赋值
return true;
}
ensureCapacityInternal()源码
private void ensureCapacityInternal(int minCapacity) {
//先调用calculateCapacity()方法再调用 ensureExplicitCapacity()方法
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
calculateCapacity()源码
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果当前数组为空数组,最小长度则为DEFAULT_CAPACITY=10;(也就是添加的时候会初始化数组长度为10)
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//否则就返回最小容量
return minCapacity;
}
calculateCapacity()返回了现在所需的最小长度
ensureExplicitCapacity()源码
private void ensureExplicitCapacity(int minCapacity) {
//保证线程安全
modCount++;
// 如果最小长度大于先在数组的长度,调用grow方法
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
grow()的源码
private void grow(int minCapacity) {
// 记录旧的数组长度
int oldCapacity = elementData.length;
//新的长度为元长度的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新的长度还是小于最小长度,那么新长度就为最小长度
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新长度大于数组的最大长度 MAX_ARRAY_SIZE= Integer.MAX_VALUE - 8;
if (newCapacity - MAX_ARRAY_SIZE > 0)
//调用hugeCapacity()计算新的大小
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//使用copy复制一个新的数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
分析一下hugeCapacity()源码
private static int hugeCapacity(int minCapacity) {
//如果最小长度 < 0 抛出 OutOfMemoryError()异常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//返回minCapacity和MAX_ARRAY_SIZE 比较如果 minCapacity>MAX_ARRAY_SIZE
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
2.添加到指定位置add(int index, E element)
//将元素添加到指定位置
public void add(int index, E element) {
//调用该方法判断下标
rangeCheckForAdd(index);
//再次确认新的容量
ensureCapacityInternal(size + 1); // Increments modCount!!
//调用copy方法,将元素index后面的元素后移
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//将index位置的元素赋值
elementData[index] = element;
//大小++
size++;
}
分析 rangeCheckForAdd();源码
//如果index<0或者index > size 抛出 IndexOutOfBoundsException异常
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
3.添加所有addAll(Collection<? extends E> c)
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
//确定新的容量
ensureCapacityInternal(size + numNew); // Increments modCount
//将两个数组融合
System.arraycopy(a, 0, elementData, size, numNew);
//更新长度
size += numNew;
return numNew != 0;
}
4.添加到指定位置addAll(int index, Collection<? extends E> c)
public boolean addAll(int index, Collection<? extends E> c) {
//检查下标情况
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
//确认新的容量
ensureCapacityInternal(size + numNew); // Increments modCount
//确定需要后移的数量
int numMoved = size - index;
//如果不是最后一位位移
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
//融合
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
5. 删除指定索引元素 E remove(int index)。
public E remove(int index) {
//检查下标
rangeCheck(index);
modCount++;
//获取改位置的元素
E oldValue = elementData(index);
//计算需要移动的数
int numMoved = size - index - 1;
//进行移动
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//将最后一个元素赋值为空
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//ArrayList私有的方法
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // 下次gc机制回收
}
6.根据元素值删除某个元素
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
7.获取单个元素
public E get(int index) {
//检查index的范围(如果index>=size)抛出异常
rangeCheck(index);
return elementData(index);
}
8.遍历元素
public Iterator<E> iterator() {
return new Itr();
}
itr是arraylist的一个私有内部类
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
//判断是否相等
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
//检查在遍历的时候是否被修改
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
//+1指向下一个元素
cursor = i + 1;
//记录当前元素的下标
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
//删除后cur回到上一个位置
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
9.设置元素set(int index, E element)
public E set(int index, E element) {
//检查边界
rangeCheck(index);
//老的元素
E oldValue = elementData(index);
//修改为新的元素
elementData[index] = element;
//返回老的元素
return oldValue;
}
10 判断元素是否存在
public boolean contains(Object o) {
//调用index方法
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
//如果为null
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
//使用遍历比较
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
//否则返回-1
return -1;
}
2.LinkedList
LinkedList
的特点:
- 底层实现了双向
链表
和双队列
特点 - 可以添加任意元素(元素可重复),包括 null
- 线程不安全,没有实现同步
1.默认属性
transient int size = 0;
//使用node节点来存储元素,使用的是双向链表
transient Node<E> first;
transient Node<E> last;
public LinkedList() {
}
node节点的结构
private static class Node<E> {
//元素值
E item;
//下一个节点
Node<E> next;
//上一个节点
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
2.构造方法
//无参构造
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
addALL(方法源码
//这里也调用了addAll()方法,接着向下看
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
//检查索引(index >= 0 && index <= size;)
checkPositionIndex(index);
//转化为数组
Object[] a = c.toArray();
//得到a的长度
int numNew = a.length;
//如果为0则直接返回
if (numNew == 0)
return false;
//声明两个节点
Node<E> pred, succ;
//如果index=size(用来进行追加)
if (index == size) {
succ = null;
pred = last;
} else {
//从某个位置进行插入
succ = node(index);
pred = succ.prev;
}
/*
node的源码(可以看到是用来寻找要插入的位置的节点的节点)
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
*/
//遍历数组
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);//创建个数组pre指向pred
if (pred == null)//如何前一个为空
first = newNode;//首节点就为该节点
else
pred.next = newNode; //否则pred的next就等于该节点
pred = newNode;
}
//succ为空
if (succ == null) {
last = pred; //将最后节点指向该节点
} else {
pred.next = succ; //否则关联本来的节点
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
3.添加方法
public boolean add(E e) {
linkLast(e);
/*
void linkLast(E e) {
//创建个节点指向last
final Node<E> l = last;
//创建个新的节点pre指向last
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;//更新last
if (l == null)
//如果为空fis指向该节点
first = newNode;
else
//否则
l.next = newNode;
size++;
modCount++;
}
*/
return true;
}
批量添加
//这个是上面构造方法调用的方法
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
4.删除方法
public boolean remove(Object o) {
//如果为空
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
/*
E unlink(Node<E> x) {
// assert x != null;
//复制一份当前元素
final E element = x.item;
//得到上一个和下一个元素
final Node<E> next = x.next;
final Node<E> prev = x.prev;
//如果上一个为空,则x为头结点,first指向x的下一个
if (prev == null) {
first = next;
} else {
//删除操作
prev.next = next;
x.prev = null;
}
//如果x为空表明x为为尾节点
if (next == null) {
last = prev;
} else {
//否则操作
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
*/
return true;
}
}
//相同操作
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
//调用的是removeFirst()方法
public E remove() {
return removeFirst();
}
removeFirst()源码
public E removeFirst() {
//赋值第一个元素
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
//调用unlinkFirst()
return unlinkFirst(f);
/*
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
//清空
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
//使得转移
first = next;
//如果只有一个节点的情况
if (next == null)
last = null;
else
//清空next的pre
next.prev = null;
size--;
modCount++;
return element;
}
*/
}
removeLast()源码
//和removeLast()方法相同
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
根据下标移除
public E remove(int index) {
//检查index
checkElementIndex(index);
//同样调用unlink方法node()方法获得index位置的节点,调用unlinked方法删除节点
return unlink(node(index));
}
删除链表中第一次出现的元素
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
remove方法
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
删除最后一个出现的指定元素
public boolean removeLastOccurrence(Object o) {
//使用后续遍历和删除第一个元素的原理相同
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
5.添加方法
//获取指定下标元素
public E get(int index) {
checkElementIndex(index);
//调用node()方法获取当前节点
return node(index).item;
}
获取第一个和最后一个元素的值的方法相同
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
根据元素获取下标
//使用遍历找到第一个发现的元素
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
6.修改方法
public E set(int index, E element) {
//检查下标
checkElementIndex(index);
//获取当前位置的元素
Node<E> x = node(index);
//得到当前元素的值
E oldVal = x.item;
//修改当前元素的值
x.item = element;
return oldVal;
}
7.栈的相关操作
//调用的是addFirst()方法
public void push(E e) {
addFirst(e);
}
//调用removeFirst()
public E pop() {
return removeFirst();
}
//如果头结点为空,就返回空.否则则返回头结点的值
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
8.队列相关的操纵
public boolean offer(E e) {
//在末尾添加元素调用课linkLast()方法
return add(e);
}
public E poll() {
//删除第一个节点
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
9.遍历器
//继承了父类的方法
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
3.Vector
1.默认属性
protected Object[] elementData; //存储数据的数组
protected int elementCount; //元素数量
protected int capacityIncrement; //容量增长系数(每次vector容量增加的增加值)
private static final long serialVersionUID = -2767605614048989439L; //序列化版本号
2.构造函数
//无参构造方法
public Vector() {
//默认容量为10
this(10);
}
//初始化容量构造方法
public Vector(int initialCapacity) {
//这里调用的是那另有个构造方法(增长系数为0)
this(initialCapacity, 0);
}
//指定容量和增长系数的方法
public Vector(int initialCapacity, int capacityIncrement) {
super();
//如果容量<0则抛出异常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//初始化数组容量
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
//传递集合的构造方法(和前面arraylist的实现原理相同)
public Vector(Collection<? extends E> c) {
Object[] a = c.toArray();
elementCount = a.length;
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, elementCount, Object[].class);
}
}
3.添加方法
public synchronized boolean add(E e) {
modCount++;
//调用ensureCapacityHelper()方法
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
ensureCapacityHelper()源码分析
private void ensureCapacityHelper(int minCapacity) {
//如果最小值 > 容量
if (minCapacity - elementData.length > 0)
//调用grow方法
grow(minCapacity);
}
grow源码分析
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//如果增长系数>0扩容机制就是老的容量+增长系数如果增长系数<0那就是2倍扩容
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//二倍扩容还是不够的话容量及时现在所需要的最小容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新的容量>数组最大长度,则会调用hugeCapacity()方法
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
hugeCapacity()源码分析
//这和arraylist是一样的
private static int hugeCapacity(int minCapacity) {
//如果最小容量一溢出则抛出异常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//否则
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
//将元素添加到指定位置
public void add(int index, E element) {
insertElementAt(element, index);
}
/*
public synchronized void insertElementAt(E obj, int index) {
modCount++;
//如果大于元素数量抛出异常
if (index > elementCount) {
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
//判断是否需要扩容
ensureCapacityHelper(elementCount + 1);
//调用copy方法来实现位移
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
//给元赋值
elementData[index] = obj;
elementCount++;
}
*/
public synchronized boolean addAll(int index, Collection<? extends E> c) {
modCount++;
//检查下标
if (index < 0 || index > elementCount)
throw new ArrayIndexOutOfBoundsException(index);
Object[] a = c.toArray();
int numNew = a.length;
//是否扩容
ensureCapacityHelper(elementCount + numNew);
//移动
int numMoved = elementCount - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
//赋值
System.arraycopy(a, 0, elementData, index, numNew);
elementCount += numNew;
return numNew != 0;
}
//和add方法相同但是没有返回值
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
4.删除元素
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--elementCount] = null; // Let gc do its work
return oldValue;
}
public synchronized boolean removeElement(Object obj) {
modCount++;
//计算出元素下标
int i = indexOf(obj);
/*
public synchronized int indexOf(Object o, int index) {
if (o == null) {
for (int i = index ; i < elementCount ; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = index ; i < elementCount ; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
*/
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
5.修改元素
//和arraylist相同
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
6.获取元素
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
/*
E elementData(int index) {
return (E) elementData[index];
}
*/
}
获取第一个元素
public synchronized E firstElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return elementData(0);
}
2、lastElement()
获取最后一个元素
public synchronized E lastElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return elementData(elementCount - 1);
}
HashSet源码
1.存储结构
HashSet 的底层是利用HashMap(邻接表结构)进行存储的。
hashSet 将存入的元素作为 hashMap的key,而所有key对应的value都是一个用static final 修饰的,
名为PRESENT的Object 类对象(此对象有地址引用,但是实际内容为空)。
可以存放null但是只能有一个空值
不能有重复的元素
基础属性
static final long serialVersionUID = -5024744406713321676L;
//使用hashmap来存储
private transient HashMap<E,Object> map;
// 定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final
private static final Object PRESENT = new Object();
1.构造方法
//无参构造创建一个map集合
public HashSet() {
map = new HashMap<>();
}
/*构造包含指定集合中所有元素的新集合。
* 创建的HashMap带有默认负载因子(0.75)和初始容量,
* 初始容量足以包含指定集合中的元素。
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
//后台的HashMap实例具有指定的初始容量和指定的负载因子
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
//指定初始化容量构造
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
//改用linkedHashMap存储
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
2.添加方法
//这里调用了map的put()方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
map.put()源码
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
hash()的源码
static final int hash(Object key) {
int h;
//如果key是0则为0,否则将hashcode值
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
putVal()源码
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
//声明一个存储node节点的数组,和一个node节点,int n,i
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果map的table为空或者tab.length=0;
if ((tab = table) == null || (n = tab.length) == 0)
//重新修改tab的大小
n = (tab = resize()).length;
//(n - 1) & hash计算出存放的索引存放将对应的元素赋值给P
if ((p = tab[i = (n - 1) & hash]) == null)
//如果为空的话,就存放进去
tab[i] = newNode(hash, key, value, null);
else {//如果不为null并且存在元素
//申明辅助变量
Node<K,V> e; K k;
//如果当前索引对应的链表的第一个元素和添加的元素的hash值形同并且key的内容和p指定的node节点的key是同一个对象
//将p赋值给e
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
//判断p是不是一个红黑树
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {//hash值相同但是第一个key不相同,看看链表后面有没有相同的值,如果没有直接添加
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
//添加到最后一个元素
p.next = newNode(hash, key, value, null);
//如果需要转为红黑树(是否达到8个节点,在转成红黑树时还要判断是否当前长度小于64,则会进行扩容)
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;
}
}
//如果e!=null代表改key已经存在
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
//检查现在的大小是否达到平衡负载达到的话就扩容
if (++size > threshold)
resize();
//该方法为空方法(为了让子类来重写发方法)
/*
void afterNodeAccess(Node<K,V> p) { }
*/
afterNodeInsertion(evict);
return null;
}
resize()源码(扩容机制)
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
//如果当前容量大于最大容量
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
//如果新的容量小于最大容量,并且老的容量大于默认容量
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // 临界值变为上个临界值的2倍
}
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
else {
//如果数组为空的情况计算新的大小容量默认值16,负载因子:扩容的临界值(0.75*容量)16*0.75=12
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
//创建一个新的数组
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
3.删除方法
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
//调用的map的删除方法
4.遍历器
public Iterator<E> iterator() {
return map.keySet().iterator();
} //使用map的keyset()的遍历器
LinkedHashSet
1.基础属性
LinkedHashSet继承了HashSet
2.构造方法
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
//这里调用了addAll()方法
addAll(c);
}
addAll()源码
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
//这里的add()是hashset里面的add()方法
if (add(e))
modified = true;
return modified;
}
3.添加方法
ll) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
### 3.删除方法
```java
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
//调用的map的删除方法
4.遍历器
public Iterator<E> iterator() {
return map.keySet().iterator();
} //使用map的keyset()的遍历器
LinkedHashSet
1.基础属性
LinkedHashSet继承了HashSet
2.构造方法
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
//这里调用了addAll()方法
addAll(c);
}
addAll()源码
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
//这里的add()是hashset里面的add()方法
if (add(e))
modified = true;
return modified;
}