java面试指导2019

ArrayList源码分析

System.arraycopy()和Arrays.copyOf()方法

  通过上面源码我们发现这两个实现数组复制的方法被广泛使用而且很多地方都特别巧妙。比如下面add(int index, E element)方法就很巧妙的用到了arraycopy()方法让数组自己复制自己实现让index开始之后的所有成员后移一个位置:

1/** 2 * 在此列表中的指定位置插入指定的元素。 3 *先调用 rangeCheckForAdd 对index进行界限检查;然后调用 ensureCapacityInternal 方法保证capacity足够大; 4 *再将从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。 5 */ 6 public void add(int index, E element) { 7 rangeCheckForAdd(index); 8 9 ensureCapacityInternal(size + 1); // Increments modCount!! 10 //arraycopy()方法实现数组自己复制自己 11 //elementData:源数组;index:源数组中的起始位置;elementData:目标数组;index + 1:目标数组中的起始位置; size - index:要复制的数组元素的数量; 12 System.arraycopy(elementData, index, elementData, index + 1, size - index); 13 elementData[index] = element; 14 size++; 15 }

 又如toArray()方法中用到了copyOf()方法

1/** 2 *以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 3 *返回的数组将是“安全的”,因为该列表不保留对它的引用。 (换句话说,这个方法必须分配一个新的数组)。 4 *因此,调用者可以自由地修改返回的数组。 此方法充当基于阵列和基于集合的API之间的桥梁。 5 */ 6 public Object[] toArray() { 7 //elementData:要复制的数组;size:要复制的长度 8 return Arrays.copyOf(elementData, size); 9 }
两者联系与区别

联系: 看两者源代码可以发现copyOf()内部调用了System.arraycopy()方法 区别:

  1. arraycopy()需要目标数组,将原数组拷贝到你自己定义的数组里,而且可以选择拷贝的起点和长度以及放入新数组中的位置

  2. copyOf()是系统自动在内部新建一个数组,并返回该数组。

核心扩容发方法,每次扩容原容量的1.5倍:

1/** 2 * ArrayList扩容的核心方法。 3 */ 4 private void grow(int minCapacity) { 5 // oldCapacity为旧容量,newCapacity为新容量 6 int oldCapacity = elementData.length; 7 //将oldCapacity 右移一位,其效果相当于oldCapacity /2, 8 //我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍, 9 int newCapacity = oldCapacity + (oldCapacity >> 1); 10 //然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量, 11 if (newCapacity - minCapacity < 0) 12 newCapacity = minCapacity; 13 //再检查新容量是否超出了ArrayList所定义的最大容量, 14 //若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE, 15 //如果minCapacity大于MAX_ARRAY_SIZE,则新容量则为Interger.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE。 16 if (newCapacity - MAX_ARRAY_SIZE > 0) 17 newCapacity = hugeCapacity(minCapacity); 18 // minCapacity is usually close to size, so this is a win: 19 elementData = Arrays.copyOf(elementData, newCapacity); 20 }
点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java list相关源码笔记

ArrayList的长度扩容是以1.5倍,比如原来是100,扩容之后就是150,源码是进行位运算oldCapacity11、ArrayList的add方法的核心方法:Arrays.copyOf(T\\original,intnewLength),original:原始数组newLength:新数组的长度比如将一个长度为6的数

java学习_5_21

数组的插入、删除、扩容本质上都是用的数组的复制。Java中数组的拷贝如下:System.arraycopy(Objectsrc,intsrcPos,Objectdest,intdestPos,intlength)1publicclassArrayCopy1{2publicstaticv

「JDK——ArrayList源码」超强解析,图文详解

ArrayList源码解析简介ArrayList是Java集合框架中非常常用的一种数据结构。继承自AbstractList,实现了List接口。底层基于数组来实现动态容量大小的控制,允许null值的存在。同时还实现了RandomAccess、Cloneable、Serializable接口,支持快速访问、复制、序列化操作。了解数组数组简单来说就是将所有的

2 手写Java LinkedList核心源码

上一章我们手写了ArrayList的核心源码,ArrayList底层是用了一个数组来保存数据,数组保存数据的优点就是查找效率高,但是删除效率特别低,最坏的情况下需要移动所有的元素。在查找需求比较重要的情况下可以用ArrayList,如果是删除操作比较多的情况下,用ArrayList就不太合适了。Java为我们提供了LinkedList,是用链接来实现的,我们

ASMSupport局部变量的实现

局部变量的实现git@osc地址(http://git.oschina.net/wensiqun/asmsupport)在字节码层面,每一个方法都有一个局部变量数组,用来存储当前方法的参数,在方法内声明的变量,如果是非静态方法还要存储当前方法实例的引用this。在我们平时使用java的时候,这个局部变量的大小是在源码编译成class的时候就