马上就要放假了,就写一点简单的吧!!!
1.问题1:ArrayList和LinkedList有什么区别
ArrayList是数组,LinkedList是链表
LinkedList的插入效率要快,这句话本身就存在问题!!!
当我们初始化ArrayList的长度的时候,就会发现,ArrayList的插入速度比LinkedLIst的插入速度要快!!!
2.标记接口:相当于一个flag
标识这个类有什么特性,但是这些接口都是null的
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
public interface RandomAccess {
}
public interface Cloneable {
}
public interface Serializable {
}
1.RandomAccess:该实现类支持随机访问
下标访问get(i) instanceOf(RandomAccess),对ArrayLIst进行遍历,我们查看一下ArrayList中是否有标记接口RandomAccess,如果有可以用for来遍历否则使用 迭代器
2.Cloneable:克隆 深拷贝 浅拷贝 实现了这个接口 object.clone();
浅拷贝:基本数据类型是独立的,引用类型是非独立的,拷贝的都是栈中的内容
深拷贝:抛出基本数据类型和String的引用数据类型,也调用一下clone()就可以了
java中的值传递:和浅拷贝类似也符合都是拷贝的栈中的内容
3.java.io.Serializable:序列化接口,
主要是重写版本号 serialVersionUID 类的指纹(签名)
存盘 网络传输
序列化:转化为二进制。如果反射进行更改属性,serialVersionUID 会发生改变的
反序列化:二进制转化回来。如果serialVersionUID 发生了改变,反序列化就会出错的
二.源码分析
private static final int DEFAULT_CAPACITY = 10;//默认容量
private static final Object[] EMPTY_ELEMENTDATA = {};//指定了初始长度的空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//没有指定初始长度空数组
transient Object[] elementData;//真正存在数值的数组
------------------------------------构造函数-------------------------------------
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;//设置了初始长度,但长度为0
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//没有设置初始长度,当我们执行多次new ArrayList可以节省空间,因为都指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA
}
public ArrayList(Collection<? extends E> c) {//传过来的是一个Collection
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);//复制
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
------------------------------------------add-----------------------------------------
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//如果size+1少于10,没有意义
//计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)//如果size+1>数组的length进行扩容
grow(minCapacity);
}
//扩容 做的事情就是把老的数组拷贝,让elementdata指向这个新的数组
//ArrayList默认是在尾部插入元素,所以也就是我们最开始的哪个问题,当ArrayList指定了长度以后,速度会比linkedList要快
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);//老数组进行复制
}
------------------------------add(index,element)----------------------------------------
public void add(int index, E element) {
rangeCheckForAdd(index);//检查下标
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
//指定下标移动元素,下标越靠前,需要移动的次数越多
------------------------------remove(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;
}
------------------------------remove(element)--------------------------------------------
//指定元素来删除
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) {//和reomve(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
}
------------------------------Itrator--------------------------------------------
public Iterator<E> iterator() {
return new Itr();//new了一个内部类Itr
}
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;//expectedModCount
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();//检查modcount,是否等于expecteModCount,快速失败机制
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];
}
}
----------------------------------------数组介绍-------------------------------------
数组:下标查询 连续内存 存储相同类型的元素,每一个元素占用的空间是相同的,
基本数据类型不支持泛型化,数组不支持向下转型(不支持开装箱)
不可变集合:修改会出错