纯手写集合框架(下一篇:LinkeList原理)
集合框架介绍
说明:对于以上的框架图有如下几点说明
1.所有集合类都位于java.util包下。Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。
2. 集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础。
3. 抽象类:5个抽象类(长虚线表示),对集合接口的部分实现。可扩展为自定义集合类。
4. 实现类:8个实现类(实线表示),对接口的具体实现。
5. Collection 接口是一组允许重复的对象。
6. Set 接口继承 Collection,集合元素不重复。
7. List 接口继承 Collection,允许重复,维护元素插入顺序。
8. Map接口是键-值对象,与Collection接口没有什么关系。
9.Set、List和Map可以看做集合的三大类:
List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问。
Set集合是无序集合,集合中的元素不可以重复,访问集合中的元素只能根据元素本身来访问(也是集合里元素不允许重复的原因)。
Map集合中保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value。
纯手写List框架
List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。
List接口继承于Collection接口,它可以定义一个允许重复的有序集合。因为List中的元素是有序的,所以我们可以通过使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
List接口为Collection直接接口。List所代表的是有序的Collection,即它用某种特定的插入顺序来维护元素顺序。用户可以对列表中每个元素的插入位置进行精确地控制,同时可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
ArrayList底层实现原理
1. Arraylist底层基于数组实现
private Object[] elementData;
2. Arraylist底层默认数组初始化大小为10个object数组
public ExtArraylist() throws Exception {this(10);}public ExtArraylist(int initialCapacity) throws Exception {if (initialCapacity < 0) {throw new IllegalArgumentException("初始容量不能小于0 " + initialCapacity);}elementData = new Object[initialCapacity];}
3. 添加元素后大于当前数组的长度,则进行扩容,将数组的长度增加原来数组的一半。
// 增大数组空间private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 在原来容量的基础上加上// oldCapacity/2if (newCapacity - minCapacity < 0)newCapacity = minCapacity; // 最少保证容量和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);}
Vector底层实现原理
Vector是线程安全的,但是性能比ArrayList要低。
ArrayList,Vector主要区别为以下几点:
(1):Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比;
(2):ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;
(3):Vector可以设置capacityIncrement,而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。
* @param */public interface ExtList {public void add(E object);public void add(int index, E object);public Object remove(int index);public boolean remove(E object);public int getSize();public Object get(int index);}/** * 纯手写ArrayList */public class ExtArrayList implements ExtList {// 保存ArrayList中数据的数组private transient Object[] elementData;// ArrayList实际数量private int size;public ExtArrayList() {// 默认初始容量为10this(10);}public ExtArrayList(int initialCapacity) {if (initialCapacity < 0) {throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);}// 初始化数组容量elementData = new Object[initialCapacity];}// 添加方法实现public void add(Object object) {ensureExplicitCapacity(size + 1);elementData[size++] = object;}public void add(int index, Object object) {rangeCheck(index);ensureExplicitCapacity(size + 1);System.arraycopy(elementData, index, elementData, index + 1, size - index);elementData[index] = object;size++;}public void ensureExplicitCapacity(int minCapacity) {// 如果存入的数据,超出了默认数组初始容量 就开始实现扩容if (size == elementData.length) {// 获取原来数组的长度 2int oldCapacity = elementData.length;// oldCapacity >> 1 理解成 oldCapacity/2 新数组的长度是原来长度1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1); // 3if (newCapacity < minCapacity) {// 最小容量比新容量要小的,则采用初始容量minCapacitynewCapacity = minCapacity;}// System.out.println("oldCapacity:" + oldCapacity + ",newCapacity:"// + newCapacity);elementData = Arrays.copyOf(elementData, newCapacity);}}// public void add(Object object) {// elementData[size++] = object;// // 如果存入的数据,超出了默认数组初始容量 就开始实现扩容// if (size == elementData.length) {// // 新的数组容量// int newCapacity = 2 * size;// // 实现数组扩容// Object[] newObjct = new Object[newCapacity];// for (int i = 0; i < elementData.length; i++) {// newObjct[i] = elementData[i];// }// elementData = newObjct;// }// }// 获取数据public Object get(int index) {rangeCheck(index);return elementData[index];}public Object remove(int index) {Object object = get(index);int numMoved = elementData.length - index - 1;if (numMoved > 0)System.arraycopy(elementData, index + 1, elementData, index, numMoved);elementData[--size] = null;return object;}public boolean remove(E object) {for (int i = 0; i < elementData.length; i++) {Object element = elementData[i];if (element.equals(object)) {remove(i);return true;}}return false;}private void rangeCheck(int index) {if (index >= size) {throw new IndexOutOfBoundsException("数组越界啦!");}}public int getSize() {return size;}}private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); //扩充的空间增加原来的50%(即是原来的1.5倍) if (newCapacity - minCapacity < 0) //如果容器扩容之后还是不够,那么干脆直接将minCapacity设为容器的大小 newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //如果扩充的容器太大了的话,那么就执行hugeCapacity newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } /** * 自定List接口