List
ArrayList
ArrayList注意事项
- permits all elements, including null 。ArrayList 可以加入null,并且多个。
- ArrayList是由数组来实现数据存储的。
- ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码,在多线程情况下,不建议使用ArrayList。
java
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(null);
arrayList.add(2);
arrayList.add(null);
arrayList.add("hello");
System.out.println(arrayList);
}
ArrayList底层操作机制-源码分析(重点)
- ArrayList中维护了一个Object类型的数组elementData。[debug看源码] transient Object[] elementData;
transient表示瞬间,短暂的。表示该属性不会被序列化/串行化。 - 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
- 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容 elementData为1.5倍。
注意,IDEA 默认情况下,Debug 显示的数据是简化后的,如果希望看到完整的数据需要做设置。
Vector
Vector基本介绍
import java.util.Vector;
- Vector类的定义说明
java
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- Vector底层也是一个对象数组
protected Object[] elementData;
- Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized
java
public synchronized E get(int index){
if (index >= elementCount)
throw new ArraylndexOutOfBoundsException(index);
return elementData(index);
}
4)在开发中,需要线程同步安全时,考虑使用Vector
------Vector和ArrayList比较
Vector底层结构和源码分析
java
//无参构造器
//有参数的构造
Vector vector = new Vector();
for (int i = 0; i < 10; i++) {
vector.add(i);
}
vector.add(100);
System.out.println("vector=" + vector);
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);
}
LinkedList
基本介绍
- LinkedList底层实现了双向链表和双端队列特点
- 可以添加任意元素(元素可以重复),包括null
- 线程不安全,没有实现同步
LinkedList的底层结构和操作机制
- LinkedList底层维护了一个双向链表
- LinkedList中维护了两个属性 first和 last分别指向首节点和尾节点
- 每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过 prev指向前一个,通过 next指向后一个节点。最终实现双向链表
- 所以 LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高
- 模拟一个简单的双向链表代码【代码】
见LinkedList01.java
LinkedList的增删改查
见LinkedListCRUD.java
java
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(1);
linkedList.add(2);
linkedList.add(3);
System.out.println("linkedList=" + linkedList);
//演示一个删除结点的
linkedList.remove(); // 这里默认删除的是第一个结点
//linkedList.remove(2);
System.out.println("linkedList=" + linkedList);
//修改某个结点对象
linkedList.set(1, 999);
System.out.println("linkedList=" + linkedList);
//得到某个结点对象
//get(1) 是得到双向链表的第二个对象
Object o = linkedList.get(1);
System.out.println(o);//999
//因为LinkedList 是 实现了List接口, 遍历方式
System.out.println("===LinkeList遍历迭代器====");
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println("next=" + next);
}
System.out.println("===LinkeList遍历增强for====");
for (Object o1 : linkedList) {
System.out.println("o1=" + o1);
}
System.out.println("===LinkeList遍历普通for====");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
}
debug查看源码学习
增
删
有很多种删除方式
java
linkedList.remove();//默认删除第一个节点
改
查
------LinkedList和ArrayList比较
本笔记是对韩顺平老师的Java课程做出的梳理。方便本人和观看者进行复习。