集合类源码(二)Collection之List(ArrayList, LinkedList, Vector)
ArrayList
功能
完全命名
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
简介
实现List接口的可调整大小的数组,这是个非线程安全的实现,如果需要线程安全,可以使用 List list = Collections.synchronizedList(new ArrayList(...)); 来包装。
方法
// 将ArrayList实例的容量调整为列表的当前大小。应用程序可以使用此操作最小化ArrayList实例的存储
public void trimToSize() // 增加这个ArrayList实例的容量
public void ensureCapacity(int minCapacity) // 返回列表中元素的数目。
public int size() // 如果此列表不包含任何元素,则返回true。
public boolean isEmpty() // 如果此列表包含至少一个指定的元素,则返回true。
public boolean contains(Object o) // 返回该列表中指定元素第一次出现的索引,如果该列表不包含该元素,则返回-1。
public int indexOf(Object o) // 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含该元素,则返回-1。
public int lastIndexOf(Object o) // 返回此ArrayList实例的浅拷贝。
public Object clone() // 返回一个数组,该数组按适当的顺序(从第一个元素到最后一个元素)包含列表中的所有元素。返回的数组将是“安全的”,因为这个列表不维护对它的引用。(换句话说,这个方法分配一个新数组)。因此,调用者可以自由地修改返回的数组。
public Object[] toArray() // 返回一个数组,该数组按适当的顺序包含列表中的所有元素(从第一个元素到最后一个元素);返回数组的运行时类型是指定数组的运行时类型。
public <T> T[] toArray(T[] a) // 返回列表中指定位置的元素。
public E get(int index) // 将列表中指定位置的元素替换为指定元素。
public E set(int index, E element) // 将指定的元素追加到此列表的末尾。
public boolean add(E e) // 将指定元素插入到列表中的指定位置,然后将当前位于该位置的元素和任何后续元素向右移动。
public void add(int index, E element) // 删除列表中指定位置的元素,然后将任何后续元素向左移动
public E remove(int index) // 从该列表中删除指定元素的第一个匹配项(如果存在)。如果列表不包含该元素,它将保持不变。
public boolean remove(Object o) // 从列表中删除所有元素。该调用返回后,列表将为空。
public void clear() // 将指定集合中的所有元素按照顺序追加到此列表的末尾。
public boolean addAll(Collection<? extends E> c) // 从指定位置开始,将指定集合中的所有元素插入此列表。指定位置的元素以及后续元素都将向后移动。
public boolean addAll(int index, Collection<? extends E> c) // 从该列表中删除其索引在fromIndex(包含)和toIndex(不包含)之间的所有元素。任何后续元素向左移动。
protected void removeRange(int fromIndex, int toIndex) // 从此列表中移除指定集合中包含的所有元素。
public boolean removeAll(Collection<?> c) // 仅保留此列表中包含在指定集合中的元素。换句话说,从这个列表中删除指定集合中不包含的所有元素。
public boolean retainAll(Collection<?> c) // 从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序)。
public ListIterator<E> listIterator(int index) // 返回此列表中元素的列表迭代器
public ListIterator<E> listIterator() // 按适当的顺序对列表中的元素返回一个迭代器。
public Iterator<E> iterator() // 返回指定的fromIndex(包含)和toIndex(不包含)之间的列表视图。习惯用法:从列表删除一部分元素( list.subList(from, to).clear(); )
public List<E> subList(int fromIndex, int toIndex) // 为可迭代的每个元素执行给定的操作,直到处理完所有元素或操作引发异常。
public void forEach(Consumer<? super E> action) // 在此列表中的元素上创建延迟绑定和快速故障的 Spliterator。
public Spliterator<E> spliterator() // 删除此集合中满足给定谓词的所有元素。迭代期间或由谓词抛出的错误或运行时异常将传递给调用者。
public boolean removeIf(Predicate<? super E> filter) // 将此列表中的每个元素替换为将操作符应用于该元素的结果。操作符抛出的错误或运行时异常将传递给调用者。
public void replaceAll(UnaryOperator<E> operator) // 根据制定的规则对列表进行排序
public void sort(Comparator<? super E> c)
原理
添加
public boolean add(E e) {
// 确保能容纳新元素
ensureCapacityInternal(size + 1); // Increments modCount!!
// 确保无误后,插入数组最后的位置。这里的size既起到了下标的作用,也起到了记录元素数量的作用。
elementData[size++] = e;
return true;
}
// 这里的minCapacity实际上是预期需要的最小容量。
private void ensureCapacityInternal(int minCapacity) {
// 先去计算容量(如果此时数组为空,则在默认容量大小和minCapacity之间选个最大的;否则直接返回minCapacity)
// 然后进入ensureExplicitCapacity方法
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
} private void ensureExplicitCapacity(int minCapacity) {
// 这个列表在结构上被修改的次数 +1
modCount++; // 如果需要的容量大于当前容量,则执行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 新容量 = 老容量 + 老容量/2(左移操作,等价于oldCapacity/2^1)。也就是说,新容量是老容量的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)
// 如果minCapacity为负数,抛出内存溢出异常;否则minCapacity = Integer.MAX_VALUE
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// minCapacity通常最接近实际大小,这是个胜利,奥利给!!
// 执行数组复制,根据newCapacity创建一个新数组,然后把老数据复制进来,返回新数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
删除
public boolean remove(Object o) {
if (o == null) {
// 删除一个null值,遍历数组,找到第一个匹配的,删除返回true
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
// 删除一个非null值,遍历数组,找到第一个匹配的,删除返回true
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
} private void fastRemove(int index) {
// 数组在结构上修改次数 +1
modCount++;
// 删除要移动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
} // 从指定的源阵列(从指定位置开始)复制阵列到目标阵列的指定位置。数组组件的子序列从src引用的源数组复制到dest引用的目标数组,复制的组件数量等于长度参数。
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
最后那个本地方法画图解释
contains
public boolean contains(Object o) {
// 实际上调用的是indexOf
return indexOf(o) >= 0;
} public int indexOf(Object o) {
if (o == null) {
// 如果为null,遍历寻找第一个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;
}
return -1;
}
ForEach
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
// forEach内部实际上也是for循环遍历,把每一个对象交给我们定义的处理方法处理
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
其它细节
// transient关键字标记的成员变量不参与序列化过程
transient Object[] elementData; // 当序列化的时候,会自动调用这个方法
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// size-数组元素数量;也就是说,只序列化真实存储的元素,而不是整个数组,节省了不必要的开销
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
关于transient关键字,大部分集合都用到了
优缺点
优点:查询快,但是仅限于按照index查找,其它的比如contains,是遍历查找。
缺点:添加和删除慢,要移动元素。
LinkedList
功能
完全命名
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable
简介
实现了List和Deque接口的双链表。这是非线程安全的,如果需要,可以使用 List list = Collections.synchronizedList(new LinkedList(...)); 来包装
方法
// 返回列表第一个元素
public E getFirst() // 返回列表最后一个元素
public E getLast() // 移除并返回列表第一个元素
public E removeFirst() // 移除并返回列表最后一个元素
public E removeLast() // 将指定的元素插入此列表的开头。
public void addFirst(E e) // 将指定的元素追加到此列表的末尾。这个方法等价于add(E)。
public void addLast(E e) // 如果此列表包含至少一个指定的元素,则返回true。
public boolean contains(Object o) // 返回列表中元素的数目。
public int size() // 将指定的元素追加到此列表的末尾。
public boolean add(E e) // 从该列表中删除指定元素的第一个匹配项(如果存在)。如果列表不包含该元素,它将保持不变。
public boolean remove(Object o) // 将指定集合中的所有元素按照顺序追加到此列表的末尾。
public boolean addAll(Collection<? extends E> c) // 从指定位置开始,将指定集合中的所有元素插入此列表。
public boolean addAll(int index, Collection<? extends E> c) // 从列表中删除所有元素。该调用返回后,列表将为空。
public void clear() // 返回列表中指定位置的元素。
public E get(int index) // 将列表中指定位置的元素替换为指定元素。
public E set(int index, E element) // 将指定元素插入到列表中的指定位置。
public void add(int index, E element) // 删除列表中指定位置的元素。
public E remove(int index) // 返回该列表中指定元素第一次出现的索引,如果该列表不包含该元素,则返回-1。
public int indexOf(Object o) // 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含该元素,则返回-1。
public int lastIndexOf(Object o) // 检索但不删除此列表的头(第一个元素)。
public E peek() // 检索但不删除此列表的头(第一个元素)。
public E element() // 检索并删除此列表的头(第一个元素)。
public E poll() // 检索并删除此列表的头(第一个元素)。
public E remove() // 将指定的元素添加为此列表的末尾(最后一个元素)。
public boolean offer(E e) // 将指定的元素插入此列表的开头。
public boolean offerFirst(E e) // 将指定的元素插入此列表的末尾。
public boolean offerLast(E e) // 检索但不删除此列表的第一个元素,或在此列表为空时返回null。
public E peekFirst() // 检索但不删除此列表的最后一个元素,或在此列表为空时返回null。
public E peekLast() // 检索并删除此列表的第一个元素,如果该列表为空,则返回null。
public E pollFirst() // 检索并删除此列表的最后一个元素,如果此列表为空,则返回null。
public E pollLast() // 将元素推入此列表所表示的堆栈。换句话说,将元素插入到列表的前面。这个方法相当于addFirst(E)。
public void push(E e) // 从该列表表示的堆栈中弹出一个元素。换句话说,删除并返回这个列表的第一个元素。这个方法相当于removeFirst()。
public E pop() // 删除此列表中指定元素的第一个匹配项(在从头到尾遍历列表时)。如果列表不包含该元素,它将保持不变。
public boolean removeFirstOccurrence(Object o) // 删除此列表中指定元素的最后一次出现(在从头到尾遍历列表时)。如果列表不包含该元素,它将保持不变。
public boolean removeLastOccurrence(Object o) // 从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序)。列表迭代器是【快速失败】的:如果列表在迭代器创建后的任何时候在结构上被修改(除了通过列表迭代器自己的删除或添加方法),列表迭代器将抛出ConcurrentModificationException。
public ListIterator<E> listIterator(int index) // 以相反的顺序返回deque中元素的迭代器。元素将按从最后(尾)到第一个(头)的顺序返回。
public Iterator<E> descendingIterator() // 返回该链表的浅拷贝。
public Object clone() // 返回一个数组,该数组按适当的顺序(从第一个元素到最后一个元素)包含列表中的所有元素。返回的数组将是“安全的”,因为这个列表不维护对它的引用。(换句话说,这个方法分配一个新数组)。因此,调用者可以自由地修改返回的数组。
public Object[] toArray() // 返回一个数组,该数组按适当的顺序包含列表中的所有元素(从第一个元素到最后一个元素);返回数组的运行时类型是指定数组的运行时类型。
public <T> T[] toArray(T[] a) // 在此列表中的元素上创建延迟绑定和快速失败的Spliterator。
public Spliterator<E> spliterator()
原理
添加
public boolean add(E e) {
// 插入到最后
linkLast(e);
return true;
} void linkLast(E e) {
// 获取尾指针
final Node<E> l = last;
// 创建新结点
final Node<E> newNode = new Node<>(l, e, null);
// 尾指针指向新结点
last = newNode;
if (l == null)
// 列表第一个元素
first = newNode;
else
// 添加到尾部
l.next = newNode;
// 列表大小 +1
size++;
// 列表结构更改次数 +1
modCount++;
}
删除
public boolean remove(Object o) {
if (o == null) {
// 如果删除对象为null,遍历链表,寻找第一个为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;
} 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; if (prev == null) {
// 当前元素是链表第一个元素,头指针直接指向当前元素后继。
first = next;
} else {
// 当前元素的前驱的后继指向当前元素的后继
prev.next = next;
// 当前元素的前驱置null
x.prev = null;
} if (next == null) {
// 当前元素是链表最后一个元素,尾指针直接指向当前元素前驱。
last = prev;
} else {
// 当前元素后继的前驱指向当前元素的前驱
next.prev = prev;
// 当前元素的后继置null
x.next = null;
} // 数据置null,方便回收
x.item = null;
// 链表元素数量 -1
size--;
// 链表结构修改次数 +1
modCount++;
// 返回老数据
return element;
}
实际上LinkedList还提供了push和pop,这就使得它可以发挥栈的作用,原理无非是在链表头部插入和删除,这不在赘述。
优缺点
优点:添加和删除效率比较高。只需要更改引用指向即可。
缺点:查找是从头遍历链表,最好情况第一个就是,最坏匹配到最后一个。不过如果仅限于首尾,只需要调用提供的getFirst和getLast等等方法
Vector
功能
完全命名
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
简介
Vector类实现了一个可增长的对象数组,它是线程安全的,如果不需要线程安全的实现,建议使用ArrayList代替Vector。
方法
// 将此Vector的组件复制到指定的数组中。这个Vector中下标k的项被复制到anArray的下标k中。
public void copyInto(Object[] anArray) // 将该向量的容量修剪为该向量的当前大小。如果该向量的容量大于其当前大小,则通过将其保存在字段elementData中的内部数据数组替换为一个更小的数组,将容量(Capacity)更改为size。
public void trimToSize() // 增加这个向量的容量
public void ensureCapacity(int minCapacity) // 设置这个向量的大小。如果新大小大于当前大小,则在向量的末尾添加新的空项。如果新大小小于当前大小,则额外的所有组件都将被丢弃。
public void setSize(int newSize) // 返回此向量的当前容量。
public int capacity() // 返回此向量中组件的数量
public int size() // 如果无元素,则返回true
public boolean isEmpty() // 返回此向量中组件的枚举。返回的枚举对象将生成此向量中的所有项。生成的第一个项是索引0处的项,然后是索引1处的项,以此类推。
public Enumeration<E> elements() // 如果该向量包含至少一个指定的元素,则返回true。
public boolean contains(Object o) // 返回该向量中指定元素第一次出现的索引,如果该向量不包含该元素,则返回-1。
public int indexOf(Object o) // 返回该向量中指定元素第一次出现时的索引(从指定索引向前搜索),如果没有找到该元素,则返回-1。
public int indexOf(Object o, int index) // 返回该向量中指定元素的最后一次出现的索引,如果该向量不包含该元素,则返回-1。
public int lastIndexOf(Object o) // 返回此向量中指定元素的最后一次出现的索引(从指定索引向后搜索),如果没有找到该元素,则返回-1。
public int lastIndexOf(Object o, int index) // 返回指定索引处的组件。此方法在功能上与get(int index)方法相同(后者是List接口的一部分)。
public E elementAt(int index) // 返回此向量的第一个组件(索引为0的项)。
public E firstElement() // 返回向量的最后一个组件。
public E lastElement() // 将此向量的指定索引处的组件设置为指定对象。索引的值必须大于或等于0,并且小于向量的当前大小。此方法在功能上与set(int, E)方法(它是List接口的一部分)相同。注意,set方法颠倒了参数的顺序,以便更接近数组的用法。set方法返回存储在指定位置的旧值。
public void setElementAt(E obj, int index) // 删除指定索引处的组件。索引的值必须大于或等于0,并且小于向量的当前大小。该方法在功能上与remove(int)方法相同(后者是List接口的一部分)。注意,remove方法返回存储在指定位置的旧值。
public void removeElementAt(int index) // 在指定索引处将指定对象作为此向量中的组件插入。这个向量中索引大于或等于指定索引的每个分量向上移动,使索引大于先前的值。索引的值必须大于或等于0,并且小于或等于向量的当前大小。(如果索引等于向量的当前大小,则将新元素追加到向量。)此方法在功能上与add(int, E)方法(List接口的一部分)相同。注意,add方法颠倒了参数的顺序,以便更接近于匹配数组的使用。
public void insertElementAt(E obj, int index) // 将指定的组件添加到该向量的末尾,将其大小增加1。此方法在功能上与add(E)方法(List接口的一部分)相同。
public void addElement(E obj) // 从这个向量中移除第一个匹配到的元素。此方法在功能上与remove(Object)方法(List接口的一部分)相同。
public boolean removeElement(Object obj) // 从这个向量中移除所有的分量,并将其大小设置为0。此方法在功能上与clear()方法(List接口的一部分)相同。
public void removeAllElements() // 返回此向量的克隆。副本将包含对内部数据数组的克隆的引用,而不是对这个向量对象的原始内部数据数组的引用。
public Object clone() // 返回一个数组,该数组顺序包含这个向量中的所有元素。
public Object[] toArray() // 返回一个数组,该数组顺序包含这个向量中的所有元素。返回数组的运行时类型是指定数组的运行时类型
public <T> T[] toArray(T[] a) // 返回该向量中指定位置的元素。
public E get(int index) // 将此向量中指定位置的元素替换为指定元素。
public E set(int index, E element) // 将指定的元素附加到此向量的末尾。
public boolean add(E e) // 移除此向量中指定元素的第一个匹配项,如果该向量不包含该元素,则该元素将保持不变。
public boolean remove(Object o) // 将指定元素插入到此向量的指定位置。
public void add(int index, E element) // 移除此向量中指定位置的元素。
public E remove(int index) // 从这个向量中移除所有的元素。
public void clear() // 如果该向量包含指定集合中的所有元素,则返回true。
public boolean containsAll(Collection<?> c) // 将指定集合中的所有元素按照指定集合的迭代器返回的顺序追加到此向量的末尾。
public boolean addAll(Collection<? extends E> c) // 从该向量中移除指定集合中包含的所有元素。
public boolean removeAll(Collection<?> c) // 仅保留此向量中包含在指定集合中的元素。换句话说,从这个向量中删除指定集合中不包含的所有元素。
public boolean retainAll(Collection<?> c) // 将指定集合中的所有元素插入到此向量的指定位置。
public boolean addAll(int index, Collection<? extends E> c) // 将指定的对象与此向量进行比较以确定是否相等。当且仅当指定的对象也是一个列表时,才返回true,两个列表的大小相同,且两个列表中所有对应的元素对都是相等的。
public boolean equals(Object o) // 返回此向量的哈希码值
public int hashCode() // 返回此向量的字符串表示形式,其中包含每个元素的字符串表示形式。
public String toString() // 返回该列表中fromIndex(包含)和toIndex(不包含)之间的元素。
public List<E> subList(int fromIndex, int toIndex) // 删除该列表中fromIndex(包含)和toIndex(不包含)之间的元素。
protected void removeRange(int fromIndex, int toIndex) // 从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序)。
public ListIterator<E> listIterator(int index) // 返回该列表中元素的列表迭代器(按适当的顺序)。
public ListIterator<E> listIterator() // 按适当的顺序对列表中的元素返回一个迭代器。
public Iterator<E> iterator() // 为可迭代的每个元素执行给定的操作,直到处理完所有元素或操作引发异常。
public void forEach(Consumer<? super E> action) // 删除此集合中满足给定谓词的所有元素。迭代期间或由谓词抛出的错误或运行时异常将传递给调用者。
public boolean removeIf(Predicate<? super E> filter) // 将此列表中的每个元素替换为将操作符应用于该元素的结果。操作符抛出的错误或运行时异常将传递给调用者。
public void replaceAll(UnaryOperator<E> operator) // 根据比较器产生的顺序对这个列表进行排序。
public void sort(Comparator<? super E> c) // 在此列表中的元素上创建延迟绑定和快速失败的Spliterator。
public Spliterator<E> spliterator()
原理
添加
// 与ArrayList唯一的区别就是加了个同步关键字,以保证线程安全,内部逻辑一样
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
} private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} 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);
} public boolean remove(Object o) {
return removeElement(o);
}
删除
// 与ArrayList唯一的区别就是加了个同步关键字,以保证线程安全,内部逻辑一样
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
} public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
get
// 注意,读取的方法也是加了同步的
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index); return elementData(index);
}
优缺点
优缺点和ArrayList大致一样,唯一的不同就是Vector是线程安全的,但是加了同步方法,也就降低了效率,如果没有线程安全问题,直接使用ArrayList即可。
集合类源码(二)Collection之List(ArrayList, LinkedList, Vector)的更多相关文章
- 源码分析(5)-ArrayList、Vector和LinkedList(JDK1.8)
一.概述 1.线程安全:ArrayList和LinkedList非线程安全的.Vector线程安全的. 2.底层数据结构:ArrayList和Vector底层数据结构是数组:LinkedList双向链 ...
- 源码小结:Java 集合ArrayList,LinkedList 源码
现在这篇主要讲List集合的三个子类: ArrayList 底层数据结构是数组.线程不安全 LinkedList 底层数据结构是链表.线程不安全 Vector 底层数据结构是数组.线程安全 Array ...
- JDK1.7源码阅读tools包之------ArrayList,LinkedList,HashMap,TreeMap
1.HashMap 特点:基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 Has ...
- Java集合类源码分析
常用类及源码分析 集合类 原理分析 Collection List Vector 扩充容量的方法 ensureCapacityHelper很多方法都加入了synchronized同步语句,来保 ...
- Java集合类源码解析:Vector
[学习笔记]转载 Java集合类源码解析:Vector 引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector.为什么说是它兄弟呢?因为从容器的构造来说,Vec ...
- JDK8集合类源码解析 - HashSet
HashSet 特点:不允许放入重复元素 查看源码,发现HashSet是基于HashMap来实现的,对HashMap做了一次“封装”. private transient HashMap<E,O ...
- Java集合类源码解析:HashMap (基于JDK1.8)
目录 前言 HashMap的数据结构 深入源码 两个参数 成员变量 四个构造方法 插入数据的方法:put() 哈希函数:hash() 动态扩容:resize() 节点树化.红黑树的拆分 节点树化 红黑 ...
- JMeter 源码二次开发函数示例
JMeter 源码二次开发函数示例 一.JMeter 5.0 版本 实际测试中,依靠jmeter自带的函数已经无法满足我们需求,这个时候就需要二次开发.本次导入的是jmeter 5.0的源码进行实际的 ...
- Unity UGUI图文混排源码(二)
Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...
- AQS源码二探-JUC系列
本文已在公众号上发布,感谢关注,期待和你交流. AQS源码二探-JUC系列 共享模式 doAcquireShared 这个方法是共享模式下获取资源失败,执行入队和等待操作,等待的线程在被唤醒后也在这个 ...
随机推荐
- CentOS 6.9安装MySQL 5.6 (使用yum安装)
CentOS 6.9安装MySQL 5.6 (使用yum安装) 移除CentOS默认的mysql-libs [root@test01 srv]# whereis mysqlmysql: /usr/li ...
- 前端之:js
JavaScript概述 ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组织ECM ...
- 操作系统原理之I/O设备管理(第六章上半部分)
一.I/O系统的组成 I/O系统不仅包括各种I/O设备,还包括与设备相连的设备控制器,有些系统还配备了专⻔⽤ 于输⼊/输出控制的专⽤计算机,即通道.此外,I/O系统要通过总线与CPU.内存相连. I/ ...
- SQLServer 高效 分页存储过程
/********************************************************************** 参数:@PrimaryKey 主键,@OrderBy 排 ...
- Python3返回函数
函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): ax = ...
- X264-编码模块和NAL打包输出
在上一篇介绍了编码器的VCL编码操作,分析了函数x264_slice_write().函数x264_slice_write()里有四个关键模块,分别是宏块分析模块.宏块编码模块.熵编码模块和滤波模块, ...
- jdbc、Mybatis、Hibernate介绍(非原创)
文章大纲 一.jdbc介绍二.Mybatis介绍三.Hibernate介绍四.jdbc.Mybatis.Hibernate比较五.参考文章 一.jdbc介绍 1. jdbc编程步骤 (1)加载数据 ...
- RabbitMQ启动报unknown exchange type 'x-delayed-message'
RabbitMQ延迟队列插件未安装,导致以下问题: ShutdownSignalException: connection error; protocol method: #method<con ...
- 2.dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian 的数据
作者:中华石杉 面试题 dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的? 面试官心理分析 上一个问题,说说 dubbo ...
- 数据库操作之DBUtils
概述 DBUtils是Java编程中的数据库操作实用工具,小巧简单实用. DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码. DBUtils三个核心功能介绍 QueryRunne ...