一:Vector 深入理解
1.1 Vector 基本介绍与注意事项‘
基本介绍:
1) Vector 类的定义说明:
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ }
2) Vector 底层也是一个对象数组, protected Object[ ] elementData;
3) Vector 是线程同步的,即线程安全, Vector 类的操作方法带有 synchronized
例如我们常用的 get 方法
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
4) 在开发过程中,需要线程同步安全时, 考虑使用 Vector。
1.2 Vector 底层结构与 ArrayList 的比较:
1. new Vector() 底层
public Vector() {
this(10);
}
补充:如果是 Vector vector = new Vector(8);
走的方法:
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
2. vector.add(i)
2.1 //下面这个方法就添加数据到vector集合
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
2.2 //确定是否需要扩容 条件 : minCapacity - elementData.length>0
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
2.3 //如果 需要的数组大小 不够用,就扩容 , 扩容的算法
//newCapacity = oldCapacity + ((capacityIncrement > 0) ?
// capacityIncrement : oldCapacity);
//就是扩容两倍.
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);
}
注意: capacityIncrement 默认为 0 ,newCapacity 默认扩容两倍。
Vector 构造器追入,源码展示:
二:LinkedList 的深入理解:
2.1 LinkedList 的全面说明:
1) LinkedList 底层实现了双向链表和双端队列的特点。
2) 可以添加任何元素(元素可以重复),包括 null
3) 线程不安全,没有实现同步。
2.2 LinkedList 的底层操作机制:
1) LinkedList 底层维护了一个双向链表。
2) LinkedList 中维护了两个属性 first 和 last,分别指向 首节点 和 尾节点。
3) 每个节点(Node 对象),里面维护了prev,next,item三个属性,其中通过 prev 指向前一个,通过 next 指向后一个 节点,最终实现双向链表。
4) 所以 LinkedList 的元素的添加与删除,不是通过数组完成的,相对来说效率比较高。
5) 模拟一个简单的双向链表,见下面代码。
public class LinkedList01 {
public static void main(String[] args) {
// 模拟一个简单的双向链表
Node jack = new Node("jack");
Node tom = new Node("tom");
Node mary = new Node("mary");
// 连接三个节点
// jack -> tom -> mary
jack.next = tom;
tom.next = mary;
//mary -> tom -> jack
mary.prev = tom;
tom.prev = jack;
Node first = jack; // 让first 引用指向jack,就是双向链表的头节点
Node last = mary; // 让last 引用指向 mary ,就是双向链表的尾节点
// 演示从头到尾遍历
while (true){
if(first == null){
break;
}
// 输出 first 的信息
System.out.println(first);
first = first.next;
}
// 演示从尾到头遍历
while (true){
if(last == null){
break;
}
System.out.println(last);
last = last.prev;
}
// 演示双向链表添加对象 , 要求在tom 与 mary 之间
Node bob = new Node("Bob");
bob.next = mary;
bob.prev = tom;
mary.prev = bob;
tom.next = bob;
}
}
// 定义一个Node类,Node 对象,表示我们双向链表的一个节点
class Node{
public Object item; // 真正存放数据的地方
public Node next; // 指向下一个节点
public Node prev; // 指向前一个节点
public Node(Object item) {
this.item = item;
}
@Override
public String toString() {
return "Node name = " + item;
}
}
2.3 LinkedList 的底层结构:
1) LinkedList 的创建分析
语句: LinkedList linkedList = new LinkedList();
调用: public LinkedList() {}
这时 linkeList 的属性 first = null last = null
2)LinkedList 的 add 分析
添加
第一步执行的方法
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;
size++;
modCount++;
}
3)LinkedList 的remove()分析
linkedList.remove(); 这里默认删除的是第一个结点
1. 执行 removeFirst
public E remove() {
return removeFirst();
}
2. 执行
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
3. 执行 unlinkFirst, 将 f 指向的双向链表的第一个结点拿掉
private E unlinkFirst(Node<E> f) {
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.prev = null;
size--;
modCount++;
return element;
}
4) linkedList.set(int index,Object obj) : 修改某个节点对象。
5) linkedList.get(int index) : 获取index索引位置的节点对象。
6)LinkedList 实现了 List 接口,遍历方法可以是 迭代器 和 增强for循环。
2.4 LinkedList 与 ArrayList 的比较
注意:ArrayList 与 LinkedList 都是线程不安全的,所以在使用的时候最好是单线程的情况下。