2021.2.3随笔
// 底层结构 --> 扩容机制/初始容量 --> null,重复,有序 --> 线程安全 --> 横向对比
(记住这个顺序,要有逻辑的描述出来)
逻辑:线性表/树/图/集合
物理:数组/链表
数组:初始容量/扩容
ArrayList 的特点(重点)
ArrayList 是 List 的一个具体实现类( List 是 Collection 的线性表子接口)
ArrayList 是 List 的一个数组实现( ArrayList 里面必定维护了一个数组)
ArrayList 允许重复,允许 null ,有序( List:线性表:除了头尾元素之外,这个序列每个元素都有唯一的前驱和后继 --> 有序 --> 有下标)
ArrayList 线程不安全
扩容机制:扩为原来的 1.5 倍
默认的数组的初始容量是 10
注意:默认的构造方法,并不能直接给我们创建一个长度为 10 的数字
ArrayList源码分析1
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("zs");
class ArrayList<E> {
// ArrayList底层所维护的数组
transient Object[] elementData;
// 空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 记录这个容器存储多少个元素
// size = 0
int size;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public boolean add(E e) {
// 参数检查/扩容
// 1; 一般在初始情况, 创建默认为10的数组
// 2; 如果数组满了, 扩容
ensureCapacityInternal(size + 1);
// 初始情况下, 必定创建一个长度为10的数组
elementData[size] = e;
size++;
return true;
}
private static final int DEFAULT_CAPACITY = 10;
// minCapacity = 1
private void ensureCapacityInternal(int minCapacity) {
// elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA: 真
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 10 1
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
// minCapacity = 10
}
// minCapacity = 10
ensureExplicitCapacity(minCapacity);
}
// minCapacity = 10
private void ensureExplicitCapacity(int minCapacity) {
modCount++;// 记录这个对象(ArrayList)被修改的次数
// 10 - 0 > 0 真
if (minCapacity - elementData.length > 0)
grow(minCapacity);// 扩容方法
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// minCapacity = 10
private void grow(int minCapacity) {
// oldCapacity = 0 // 空数组的长度 --->旧长度 0
int oldCapacity = elementData.length;
// newCapacity = 1.5 oldCapacity ---> 扩容机制: 扩为原来的1.5倍
// newCapacity = 0
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 0 - 10 < 0 真
if (newCapacity - minCapacity < 0)
// newCapacity = 10
newCapacity = minCapacity;
// 10 - 假
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// Arrays.copyOf 复制方法 ; 复制的来源elementData, 复制多长newCapacity 10
// 产生了一个长度为10的数组, 赋值给elementData
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
ArrayLisi 源码分析2
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
// 如果给定长度大于0,那么直接创建一个数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
ArrayList<String> list = new ArrayList<>();
// ArrayList(Collection<? extends E> c)
// 要求 当作参数传进来的集合类里面存储的参数类型
// 应该是,当前集合类对象存储参数类型的相同或者子类
ArrayList<Object> list1 = new ArrayList<>(list);
public ArrayList(Collection<? extends E> c) {
// c.toArray();// 把c这个Collection集合类转化为数组
// 用这个经过转化的数组,来充当,此时创建对象的底层数组
elementData = c.toArray();
// size = elementData.length // 同步集合类存储数据的个数
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
// 如果 c.toArray();返回的不是一个Object类型的数组,那么就转化为一个 Object 类型的数组。
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
// 置空
this.elementData = EMPTY_ELEMENTDATA;
}
}
public void ensureCapacity(int minCapacity) {
// 100
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;
// 100 > 0 ?
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
// 100
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
// 100 - 10 > 0 真
if (minCapacity - elementData.length > 0)
// 扩容(100)
grow(minCapacity);
}
private void grow(int minCapacity) {
// oldCapaCity = 10
int oldCapacity = elementData.length;
// oldCapaCity = 15
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 15 - 100 < 0
if (newCapacity - minCapacity < 0)
//newCapaCity = 100
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//
elementData = Arrays.copyOf(elementData, newCapacity);
}
API
boolean add(E e)
将指定的元素添加到此列表的尾部。
void add(int index, E element)
将指定的元素插入此列表中的指定位置。
boolean addAll(Collection<? extends E> c)
按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
boolean addAll(int index, Collection<? extends E> c)
从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
void clear()
移除此列表中的所有元素。
boolean contains(Object o)
如果此列表中包含指定的元素,则返回 true。
int indexOf(Object o)
返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
boolean isEmpty()
如果此列表中没有元素,则返回 true
int lastIndexOf(Object o)
返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
E remove(int index)
移除此列表中指定位置上的元素。
boolean remove(Object o)
移除此列表中首次出现的指定元素(如果存在)。
protected void removeRange(int fromIndex, int toIndex)
移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。
int size()
返回此列表中的元素数。
Object[] toArray()
按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
<T> T[]
toArray(T[] a)
按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。
// 浅拷贝
Object clone()
返回此 ArrayList 实例的浅表副本。
E get(int index)
返回此列表中指定位置上的元素。
E set(int index, E element)
用指定的元素替代此列表中指定位置上的元素。
// 手动控制容量 >= 给定minCapacity //没啥用
void ensureCapacity(int minCapacity)
如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
// 就是把底层数组的长度,调整为size长度。
void trimToSize()
将此 ArrayList 实例的容量调整为列表的当前大小。
iterator()
listiterator()
ArrayList 源码分析3
ArrayList<String> list = new ArrayList<>();
list.add("zs");
list.add("ls");
list.add("ww");
list.add("zl");
// 0 1 2 3
// zs ls wu zl
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
public Iterator<E> iterator() {
return new Itr();
}
// zs ls wu zl
//lastRet cursor
// i
private class Itr implements Iterator<E> {
int cursor; // 初始值 0 : 指向下一个要遍历的位置
int lastRet = -1; // 初始值 -1 :上一次遍历的元素
// modCount 源集合类对象的修改次数
// 把迭代器的expectedModeCount 和源集合类同步
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();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
// 删除:上一次刚遍历过的元素
// 未遍历之前不能删除
// 不能连续删除
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
// 相当于调用源集合类的删除方法,删除下标为lastRet位置的元素
ArrayList.this.remove(lastRet);
// cursor前移
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();
}
}
ArrayList源码分析4
public ListIterator<E> listIterator() {
return new ListItr(0);
}
// zs ls ww wl
private class ListItr extends Itr implements ListIterator<E> {
int cursor; // 标记要遍历的元素
int lastRet = -1; // 上一个遍历的元素
int expectedModCount = modCount;// 同步修改次数
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
// 向前遍历
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();// 检查并发修改异常
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
// cursor 前移
cursor = i;
return (E) elementData[lastRet = i];
}
// 修改 : 修改的是刚刚遍历过的“位置” --> 可以连续修改,没遍历之前是不可以修改的
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
// 直接调用源集合类的修改方面,并且把需要修改的位置,传递过去
ArrayList.this.set(lastRet, e);
// 修改不需要同步modCount
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
// 添加的位置,光标所在的位置
// 添加元素之后,可以删除吗?不可以,因为lastRet=-1。
// 添加元素之后,可以修改吗?不可以,
// 可以添加吗?可以
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
Itr() {}
public boolean hasNext() {
return cursor != size;
}
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();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
ArrayList 源码分析5
ArrayList<String> list = new ArrayList<>();
list.add("zs");
list.add("ls");
list.add("ww");
list.add("zl");
System.out.println(list);
public String toString() {
// 相当于
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
// 遍历到没有元素,null是有元素的
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
补充:
ArrayList 的 toString 方法,是继承来的,里面实现的逻辑实际上是一个iterrator迭代
Vector 概述
Vector:向量,矢量:有大小有方向
底层结构是数组
默认初始容量(10),扩容机制(默认机制扩为原来的2倍)
Null,重复,有序
线程安全
扩容:“增量”,我们可以控制 Vector 每次扩容的大小
Vector 源码分析1
Vector<String> vector = new Vector<>();
vector.add("zs");
elementData // 集合类数组
public Vector() {
this(10);
}
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
总结:摸鱼的一天,LeeCode每日都没刷过去,今天就干了一件事,复制粘贴源码。。希望大家别学我