一丶概述
面试:说说HashMap的底层实现原理?
小明:Android开发平时用ArrayList就够了,很少用HashMap。
面试:那你说说ArrayList
小明:。。。。
面试都喜欢问HashMap底层原理,而ArrayList是最长用到的,先说说ArrayList
二丶源码与原理
1.初始化
/** * ArrayList初始化默认容量大小为10,见无参构造函数。 */private static final int DEFAULT_CAPACITY = 10;/** * 空实例共享的空数组实例。 */private static final Object[] EMPTY_ELEMENTDATA = {};/** * ArrayList成员存储在这个数组缓冲区中。 * 容量大小是这个缓冲区的长度 * 在添加第一个成员时都会扩充到DEFAULT_CAPACITY大小,即容量为10。 * transient这个关键字告诉我们该对象在序列化的时候请忽略这个元素 */transient Object[] elementData;/** * 逻辑长度 */private int size;/** * 传入长度 */public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; }/** * 初始化长度为10的数组 */public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; }/** *创建一个包含collection的ArrayList */public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }
image.png
说名:1:ArrayList底层是Object[]数组;2.空ArrayList指向同一个空数组,3.默认长度为10;
2.add方法:当ArrayList加入对象呢?
/**返回永远为true 无限扩容*/public boolean add(E e) { // 确定ArrayList的容量大小 ensureCapacityInternal(size + 1); // Increments modCount!! //添加e到ArrayList中 elementData[size++] = e; return true; }
/**指定位置添加元素*/public void add(int index, E element) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
/**添加一个元素*/public void add(E e) { if (modCount != expectedModCount) throw new ConcurrentModificationException(); try { int i = cursor; ArrayList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = modCount; limit++; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } }
/**确定ArrarList的容量*/private void ensureCapacityInternal(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }/**判断是否需要扩容*/private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
3.ArrayList扩容原理
/**扩容1.5倍,并重新copy值*/private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; // 若ArrayList的容量不足以容纳当前的全部元素则*1.5,设置 新的容量=“oldCapacity + (oldCapacity >> 1) int newCapacity = oldCapacity + (oldCapacity >> 1); 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); }
人工数组扩容方法图解(换成ArrayList的话这里大小控制为1.5倍,就对啦):
image.png
image.png
4.Arrays.copyof()和System.arraycopy()方法
Arrays.copyof()
public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); }
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
System.arraycopy()
/** *native修饰为用其它语言(C/C++)实现方法 * @param src 要拷贝的数组 * @param srcPos 要拷贝数组起始位置 * @param dest 目标数组 * @param destPos 目标数组要拷贝的起始位置 * @param length 要拷贝长度 */public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
5.其他方法(略)
fill :填充元素
remove:删除元素,后面元素会前移
fastremove:截取后部分
......
6.特点
image.png
7.时间复杂度
底层数组存/取元素效率非常的高(get/set),时间复杂度是O(1),而查找,插入和删除元素效率似乎不太高,时间复杂度为O(n)。
作者:天一方蓝
链接:https://www.jianshu.com/p/7de5c2bcdca3
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦