写点什么

MySQL InnoDB 事务隔离级别的实现原理,linux 群集部署架构

用户头像
极客good
关注
发布于: 刚刚

1 /**


2 * Appends the specified element to the end of this list.


3 *


4 * @param e element to be appended to this list


5 * @return <tt>true</tt> (as specified by {@link Collection#add})


6 */


7public boolean add(E e) {


8 ensureCapacityInternal(size + 1); // Increments modCount!!


9 elementData[size++] = e;


10 return true;


11}


该方法是在集合中追加元素。其中核心方法是 ensureCapacityInternal,意思是确定集合内部容量。


1private void ensureCapacityInternal(int minCapacity) {


2 ensureExplicitCapacity(


3 calculateCapacity(elementData,minCapacity));


4}


5


6private static int calculateCapacity(Object[] elementData, int


7 minCapacity) {


8 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {


9 return Math.max(DEFAULT_CAPACITY, minCapacity);


10 }


11 return minCapacity;


12}


这里首先计算了集合的容量,如果这个 ArrayList 是通过无参构造创建的,那么比较默认值 10,以及传入的 minCapacity,取最大值,这里可能有的同学会有疑问,为什么要比较默认值和 minCapacity,默认值不是一定大于 minCapacity 吗?,这里是因为 ensureCapacityInternal 这个方法不仅仅是 add()会调用,allAll()也会调用。


1public boolean addAll(int index, Collection<? extends E> c) {


2 rangeCheckForAdd(index);


3


4 Object[] a = c.toArray();


5 int numNew = a.length;


6 ensureCapacityInternal(size + numNew); // Increments modCount


7 //省略部分代码..


8 }


这里如果 numNew 大于 10,那么默认值就会不够用。所以才会在 calculateCapacity 方法中引入一个求最大值的步骤。


算出集合存储数据所需的最小空间后,就要考虑,集合原有存储空间是否够用,是否需要扩容。


1private void ensureExplicitCapacity(int minCapacity) {


2 modCount++;


3 // overflow-conscious code


4 if (minCapacity - elementData.length > 0)


5 grow(minCapacity);


6}


7


8/**


9 * Increases the capacity to ensure that it can hold at least the


10 * number of elements specified by the minimum capacity argument.


11 *


12 * @param minCapacity the desired minimum capacity


13 */


14 private void grow(int minCapacity) {


15 // overflow-conscious code


16 int oldCapacity = elementData.length;


17 int newCapacity = oldCapacity + (oldCapacity >> 1);


18 if (newCapacity - minCapacity < 0)


19 newCapacity = minCapacity;


20 if (newCapacity - MAX_ARRAY_SIZE > 0)


21 newCapacity = hugeCapacity(minCapacity);


22 // minCapacity is usually close to size, so this is a win:


23 elementData = Arrays.copyOf(elementData, newCapacity);


24}


这里我们


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


主要关注 4 个点:


1.int newCapacity = oldCapacity + (oldCapacity >> 1);每次扩容是原数组的 1.5 倍


2.扩容也是有限的,存在最大值:MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8


3.集合扩容底层调用的是:Arrays.copyOf()方法,需要把数组中的数据复制一份,到新数组中,而这个方法底层是 System.arrayCopy 是一个 native 方法,效率不高。


4.最重要的一个点:如果我们可以事先估计出数据量,那么最好给 ArrayList 一个初始值,这样可以减少其扩容次数,从而省掉很多次内存申请和数据搬移操作。(不指定初始值,至少会执行一次 grow 方法,用于初始化内部数组)。

3.remove()

1/**


2 * Removes the element at the specified position in this list.


3 * Shifts any subsequent elements to the left (subtracts one from their


4 * indices).


5 *


6 * @param index the index of the element to be removed


7 * @return the element that was removed from the list


8 * @throws IndexOutOfBoundsException {@inheritDoc}


9 */


10public E remove(int index) {


11 rangeCheck(index);


12 modCount++;


13 E oldValue = elementData(index);


14


15 int numMoved = size - index - 1;


16 if (numMoved > 0)


17 System.arraycopy(elementData, index+1, elementData, index,


18 numMoved);


19 elementData[--size] = null; // clear to let GC do its work


20 return oldValue;


21}


删除的代码因为不涉及到缩容,所以比起 add 较为简单,首先会检查数组是否下标越界,然后会获取指定位置的元素,接着进行数据的搬移,将--size 位置的元素置成 null,让 GC 进行回收。最后将目标元素返回即可。


另外最后我想提出一个比较容易犯的错误,集合在遍历的时候,对其结构进行修改(删除、新增元素)。举一个例子:


1public class Test {


2 public static void main(String[] args) {


3 List<Integer> list = new ArrayList<>();


4 list.add(1);


5 list.add(2);


6 list.add(3);


7 for (Integer i : list) {


8 if(i.equals(1)){


9 list.remove(i);


10 }


11 }


12 }


13}


结果:

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
MySQL InnoDB 事务隔离级别的实现原理,linux群集部署架构