1.ArrayList
先了解两种访问方式,随机访问与顺序访问
顺序访问:在一组长度为n的数据中,要找到其中的第i个元素,只能从头到尾的遍历,直到找到第i个元素。
就是遍历地查询我想要的元素呗。
随机访问(直接访问):在一组长度为n的数据中,要找到其中的第i个元素,只需要通过下标就能访问到。
就是根据索引就能直接访问到我想访问的元素
其中数组就可以进行随机访问不是嘛?比如,array[i]。
数组在内存中的存储结构是像一个火车一样,一节一节的。
例如java中int的长度是4字节(32位),起始地址0x00000001,即“车头”的开始位置,那么下一节“车厢”的开始位置为0x00000033,
依次类推0x00000065…所以数组中索引为0的数据位置就在0x000000001~0x00000032中。
这样的话,知道了起始地址,和数据长度,就可以实现随机访问。
比如访问array[2],array[2]数据的起始地址:0x00000001 + 32 * 2
好了那下面看看源码
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Note that this implementation is not synchronized.
AbstractList
Collection接口
这里面定义了一些对集合内元素的处理方法
List接口
继承了Collection接口,在Collection定义的方法的基础上,又增加了一些方法。
AbstractCollection抽象类
1.实现类Collection接口中的方法,即能对数组进行操作了。
但是,返回数组大小和遍历器遍历的方法没有实现。
AbstractList
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
它有两个内部类
这俩内部类是遍历用的。
private class ListItr extends Itr implements ListIterator<E>
private class Itr implements Iterator<E>
还有两个同级的类
class SubList<E> extends AbstractList<E>
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess
SubList 其实就是一个新的AbstractList,返回一个新的被截取的链表用的。官方文档称为视图。
RandomAccessSubList继承了SubList,实现了RandomAccess。而RandomAccess是个空空如也的接口,
里面的注释有这样一句话
marker interface used by List implementations to indicate that they support fast (generally constant time) random access.
所以这个接口就是一个标志,标志着这个类使用索引遍历比迭代器要快。
ArrayList
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
终于到了研究ArrayList这一部了
同样,ArrayList里面也有Ltr , Listltr,SubList三个内部类,其中Ltr是完全一样的,这里算不算代码重复呢?
其中还有ArrayListSpliterator内部类。(TODO)
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
contains()方法
调用了indexOf()方法,根据返回的索引值是否大于等于0,来判断是否存在。
而indexOf()方法是,是通过遍历查询的。
array的排序,是调用了Arrays.sort() ,
Arrays.sort() 对于小数组,用的是插入排序的方法。
对于超过了界定的小数组的长度,用递归排序。
下面是具体源码
private static void mergeSort(Object[] src,
Object[] dest,
int low, int high, int off,
Comparator c) {
int length = high - low;
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
// Recursively sort halves of dest into src
int destLow = low;
int destHigh = high;
low += off;
high += off;
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off, c);
mergeSort(dest, src, mid, high, -off, c);
// If list is already sorted, just copy from src to dest. This is an
// optimization that results in faster sorts for nearly ordered lists.
if (c.compare(src[mid-1], src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
// Merge sorted halves (now in src) into dest
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
dest[i] = src[p++];
else
dest[i] = src[q++];
}
}
…其他的方法其实点进去看看也就明白了。不想再花时间做了。
这些都不太重要,重要的是ArrayList其实就是维护了个数组。
肝了一天的源代码,突然觉得我人傻了。