当前位置: 首页 > news >正文

深圳建设局网站首页网页设计教程完整

深圳建设局网站首页,网页设计教程完整,wordpress是PHP框架吗,的的平台服务电话1. ArrayList 简介 ArrayList 的底层是数组队列#xff0c;相当于动态数组。与 Java 中的数组相比#xff0c;它的容量能动态增长。在添加大量元素前#xff0c;应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。 ArrayLis…1. ArrayList 简介 ArrayList 的底层是数组队列相当于动态数组。与 Java 中的数组相比它的容量能动态增长。在添加大量元素前应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。 ArrayList继承于 AbstractList 实现了 List, RandomAccess, Cloneable, java.io.Serializable 这些接口。 public class ArrayListE extends AbstractListEimplements ListE, RandomAccess, Cloneable, java.io.Serializable{}RandomAccess 是一个标志接口表明实现这个这个接口的 List 集合是支持快速随机访问的。在 ArrayList 中我们即可以通过元素的序号快速获取元素对象这就是快速随机访问。ArrayList 实现了 Cloneable 接口 即覆盖了函数clone()能被克隆。ArrayList 实现了 java.io.Serializable 接口这意味着ArrayList支持序列化能通过序列化去传输。 1.1. Arraylist 和 Vector 的区别? ArrayList 是 List 的主要实现类底层使用 Object[ ]存储适用于频繁的查找工作线程不安全 Vector 是 List 的古老实现类底层使用 Object[ ]存储线程安全的。 1.2. Arraylist 与 LinkedList 区别? 是否保证线程安全 ArrayList 和 LinkedList 都是不同步的也就是不保证线程安全底层数据结构 Arraylist 底层使用的是 Object 数组LinkedList 底层使用的是 双向链表 数据结构JDK1.6 之前为循环链表JDK1.7 取消了循环。注意双向链表和双向循环链表的区别下面有介绍到插入和删除是否受元素位置的影响 ① ArrayList 采用数组存储所以插入和删除元素的时间复杂度受元素位置的影响。 比如执行add(E e)方法的时候 ArrayList 会默认在将指定的元素追加到此列表的末尾这种情况时间复杂度就是 O(1)。但是如果要在指定位置 i 插入和删除元素的话add(int index, E element)时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。 ② LinkedList 采用链表存储所以对于add(E e)方法的插入删除元素时间复杂度不受元素位置的影响近似 O(1)如果是要在指定位置i插入和删除元素的话(add(int index, E element) 时间复杂度近似为o(n))因为需要先移动到指定位置再插入。是否支持快速随机访问 LinkedList 不支持高效的随机元素访问而 ArrayList 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。内存空间占用 ArrayList 的空 间浪费主要体现在在 list 列表的结尾会预留一定的容量空间而 LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间因为要存放直接后继和直接前驱以及数据。 2. ArrayList 核心源码解读 package java.util;import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.UnaryOperator;public class ArrayListE extends AbstractListEimplements ListE, RandomAccess, Cloneable, java.io.Serializable {private static final long serialVersionUID 8683452581122892189L;/*** 默认初始容量大小*/private static final int DEFAULT_CAPACITY 10;/*** 空数组用于空实例。*/private static final Object[] EMPTY_ELEMENTDATA {};//用于默认大小空实例的共享空数组实例。//我们把它从EMPTY_ELEMENTDATA数组中区分出来以知道在添加第一个元素时容量需要增加多少。private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA {};/*** 保存ArrayList数据的数组*/transient Object[] elementData; // non-private to simplify nested class access/*** ArrayList 所包含的元素个数*/private int size;/*** 带初始容量参数的构造函数用户可以在创建ArrayList对象时自己指定集合的初始大小*/public ArrayList(int initialCapacity) {if (initialCapacity 0) {//如果传入的参数大于0创建initialCapacity大小的数组this.elementData new Object[initialCapacity];} else if (initialCapacity 0) {//如果传入的参数等于0创建空数组this.elementData EMPTY_ELEMENTDATA;} else {//其他情况抛出异常throw new IllegalArgumentException(Illegal Capacity: initialCapacity);}}/***默认无参构造函数*DEFAULTCAPACITY_EMPTY_ELEMENTDATA 为0.初始化为10也就是说初始其实是空数组 当添加第一个元素的时候数组容量才变成10*/public ArrayList() {this.elementData DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/*** 构造一个包含指定集合的元素的列表按照它们由集合的迭代器返回的顺序。*/public ArrayList(Collection? extends E c) {//将指定集合转换为数组elementData c.toArray();//如果elementData数组的长度不为0if ((size elementData.length) ! 0) {// 如果elementData不是Object类型数据c.toArray可能返回的不是Object类型的数组所以加上下面的语句用于判断if (elementData.getClass() ! Object[].class)//将原来不是Object类型的elementData数组的内容赋值给新的Object类型的elementData数组elementData Arrays.copyOf(elementData, size, Object[].class);} else {// 其他情况用空数组代替this.elementData EMPTY_ELEMENTDATA;}}/*** 修改这个ArrayList实例的容量是列表的当前大小。 应用程序可以使用此操作来最小化ArrayList实例的存储。*/public void trimToSize() {modCount;if (size elementData.length) {elementData (size 0)? EMPTY_ELEMENTDATA: Arrays.copyOf(elementData, size);}} //下面是ArrayList的扩容机制 //ArrayList的扩容机制提高了性能如果每次只扩充一个 //那么频繁的插入会导致频繁的拷贝降低性能而ArrayList的扩容机制避免了这种情况。/*** 如有必要增加此ArrayList实例的容量以确保它至少能容纳元素的数量* param minCapacity 所需的最小容量*/public void ensureCapacity(int minCapacity) {//如果是trueminExpand的值为0如果是false,minExpand的值为10int minExpand (elementData ! DEFAULTCAPACITY_EMPTY_ELEMENTDATA)// any size if not default element table? 0// larger than default for default empty table. Its already// supposed to be at default size.: DEFAULT_CAPACITY;//如果最小容量大于已有的最大容量if (minCapacity minExpand) {ensureExplicitCapacity(minCapacity);}}//得到最小扩容量private void ensureCapacityInternal(int minCapacity) {if (elementData DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {// 获取“默认的容量”和“传入参数”两者之间的最大值minCapacity Math.max(DEFAULT_CAPACITY, minCapacity);}ensureExplicitCapacity(minCapacity);}//判断是否需要扩容private void ensureExplicitCapacity(int minCapacity) {modCount;// overflow-conscious codeif (minCapacity - elementData.length 0)//调用grow方法进行扩容调用此方法代表已经开始扩容了grow(minCapacity);}/*** 要分配的最大数组大小*/private static final int MAX_ARRAY_SIZE Integer.MAX_VALUE - 8;/*** ArrayList扩容的核心方法。*/private void grow(int minCapacity) {// oldCapacity为旧容量newCapacity为新容量int oldCapacity elementData.length;//将oldCapacity 右移一位其效果相当于oldCapacity /2//我们知道位运算的速度远远快于整除运算整句运算式的结果就是将新容量更新为旧容量的1.5倍int newCapacity oldCapacity (oldCapacity 1);//然后检查新容量是否大于最小需要容量若还是小于最小需要容量那么就把最小需要容量当作数组的新容量if (newCapacity - minCapacity 0)newCapacity minCapacity;//再检查新容量是否超出了ArrayList所定义的最大容量//若超出了则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE//如果minCapacity大于MAX_ARRAY_SIZE则新容量则为Interger.MAX_VALUE否则新容量大小则为 MAX_ARRAY_SIZE。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);}//比较minCapacity和 MAX_ARRAY_SIZEprivate static int hugeCapacity(int minCapacity) {if (minCapacity 0) // overflowthrow new OutOfMemoryError();return (minCapacity MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}/***返回此列表中的元素数。*/public int size() {return size;}/*** 如果此列表不包含元素则返回 true 。*/public boolean isEmpty() {//注意和的区别return size 0;}/*** 如果此列表包含指定的元素则返回true 。*/public boolean contains(Object o) {//indexOf()方法返回此列表中指定元素的首次出现的索引如果此列表不包含此元素则为-1return indexOf(o) 0;}/***返回此列表中指定元素的首次出现的索引如果此列表不包含此元素则为-1*/public int indexOf(Object o) {if (o null) {for (int i 0; i size; i)if (elementData[i]null)return i;} else {for (int i 0; i size; i)//equals()方法比较if (o.equals(elementData[i]))return i;}return -1;}/*** 返回此列表中指定元素的最后一次出现的索引如果此列表不包含元素则返回-1。.*/public int lastIndexOf(Object o) {if (o null) {for (int i size-1; i 0; i--)if (elementData[i]null)return i;} else {for (int i size-1; i 0; i--)if (o.equals(elementData[i]))return i;}return -1;}/*** 返回此ArrayList实例的浅拷贝。 元素本身不被复制。*/public Object clone() {try {ArrayList? v (ArrayList?) super.clone();//Arrays.copyOf功能是实现数组的复制返回复制后的数组。参数是被复制的数组和复制的长度v.elementData Arrays.copyOf(elementData, size);v.modCount 0;return v;} catch (CloneNotSupportedException e) {// 这不应该发生因为我们是可以克隆的throw new InternalError(e);}}/***以正确的顺序从第一个到最后一个元素返回一个包含此列表中所有元素的数组。*返回的数组将是“安全的”因为该列表不保留对它的引用。 换句话说这个方法必须分配一个新的数组。*因此调用者可以自由地修改返回的数组。 此方法充当基于阵列和基于集合的API之间的桥梁。*/public Object[] toArray() {return Arrays.copyOf(elementData, size);}/*** 以正确的顺序返回一个包含此列表中所有元素的数组从第一个到最后一个元素;*返回的数组的运行时类型是指定数组的运行时类型。 如果列表适合指定的数组则返回其中。*否则将为指定数组的运行时类型和此列表的大小分配一个新数组。*如果列表适用于指定的数组其余空间即数组的列表数量多于此元素则紧跟在集合结束后的数组中的元素设置为null 。*这仅在调用者知道列表不包含任何空元素的情况下才能确定列表的长度。*/SuppressWarnings(unchecked)public T T[] toArray(T[] a) {if (a.length size)// 新建一个运行时类型的数组但是ArrayList数组的内容return (T[]) Arrays.copyOf(elementData, size, a.getClass());//调用System提供的arraycopy()方法实现数组之间的复制System.arraycopy(elementData, 0, a, 0, size);if (a.length size)a[size] null;return a;}// Positional Access OperationsSuppressWarnings(unchecked)E elementData(int index) {return (E) elementData[index];}/*** 返回此列表中指定位置的元素。*/public E get(int index) {rangeCheck(index);return elementData(index);}/*** 用指定的元素替换此列表中指定位置的元素。*/public E set(int index, E element) {//对index进行界限检查rangeCheck(index);E oldValue elementData(index);elementData[index] element;//返回原来在这个位置的元素return oldValue;}/*** 将指定的元素追加到此列表的末尾。*/public boolean add(E e) {ensureCapacityInternal(size 1); // Increments modCount!!//这里看到ArrayList添加元素的实质就相当于为数组赋值elementData[size] e;return true;}/*** 在此列表中的指定位置插入指定的元素。*先调用 rangeCheckForAdd 对index进行界限检查然后调用 ensureCapacityInternal 方法保证capacity足够大*再将从index开始之后的所有成员后移一个位置将element插入index位置最后size加1。*/public void add(int index, E element) {rangeCheckForAdd(index);ensureCapacityInternal(size 1); // Increments modCount!!//arraycopy()这个实现数组之间复制的方法一定要看一下下面就用到了arraycopy()方法实现数组自己复制自己System.arraycopy(elementData, index, elementData, index 1,size - index);elementData[index] element;size;}/*** 删除该列表中指定位置的元素。 将任何后续元素移动到左侧从其索引中减去一个元素。*/public E remove(int index) {rangeCheck(index);modCount;E oldValue elementData(index);int numMoved size - index - 1;if (numMoved 0)System.arraycopy(elementData, index1, elementData, index,numMoved);elementData[--size] null; // clear to let GC do its work//从列表中删除的元素return oldValue;}/*** 从列表中删除指定元素的第一个出现如果存在。 如果列表不包含该元素则它不会更改。*返回true如果此列表包含指定的元素*/public boolean remove(Object o) {if (o null) {for (int index 0; index size; index)if (elementData[index] null) {fastRemove(index);return true;}} else {for (int index 0; index size; index)if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false;}/** Private remove method that skips bounds checking and does not* return the value removed.*/private void fastRemove(int index) {modCount;int numMoved size - index - 1;if (numMoved 0)System.arraycopy(elementData, index1, elementData, index,numMoved);elementData[--size] null; // clear to let GC do its work}/*** 从列表中删除所有元素。*/public void clear() {modCount;// 把数组中所有的元素的值设为nullfor (int i 0; i size; i)elementData[i] null;size 0;}/*** 按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。*/public boolean addAll(Collection? extends E c) {Object[] a c.toArray();int numNew a.length;ensureCapacityInternal(size numNew); // Increments modCountSystem.arraycopy(a, 0, elementData, size, numNew);size numNew;return numNew ! 0;}/*** 将指定集合中的所有元素插入到此列表中从指定的位置开始。*/public boolean addAll(int index, Collection? extends E c) {rangeCheckForAdd(index);Object[] a c.toArray();int numNew a.length;ensureCapacityInternal(size numNew); // Increments modCountint numMoved size - index;if (numMoved 0)System.arraycopy(elementData, index, elementData, index numNew,numMoved);System.arraycopy(a, 0, elementData, index, numNew);size numNew;return numNew ! 0;}/*** 从此列表中删除所有索引为fromIndex 含和toIndex之间的元素。*将任何后续元素移动到左侧减少其索引。*/protected void removeRange(int fromIndex, int toIndex) {modCount;int numMoved size - toIndex;System.arraycopy(elementData, toIndex, elementData, fromIndex,numMoved);// clear to let GC do its workint newSize size - (toIndex-fromIndex);for (int i newSize; i size; i) {elementData[i] null;}size newSize;}/*** 检查给定的索引是否在范围内。*/private void rangeCheck(int index) {if (index size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** add和addAll使用的rangeCheck的一个版本*/private void rangeCheckForAdd(int index) {if (index size || index 0)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** 返回IndexOutOfBoundsException细节信息*/private String outOfBoundsMsg(int index) {return Index: index, Size: size;}/*** 从此列表中删除指定集合中包含的所有元素。*/public boolean removeAll(Collection? c) {Objects.requireNonNull(c);//如果此列表被修改则返回truereturn batchRemove(c, false);}/*** 仅保留此列表中包含在指定集合中的元素。*换句话说从此列表中删除其中不包含在指定集合中的所有元素。*/public boolean retainAll(Collection? c) {Objects.requireNonNull(c);return batchRemove(c, true);}/*** 从列表中的指定位置开始返回列表中的元素按正确顺序的列表迭代器。*指定的索引表示初始调用将返回的第一个元素为next 。 初始调用previous将返回指定索引减1的元素。*返回的列表迭代器是fail-fast 。*/public ListIteratorE listIterator(int index) {if (index 0 || index size)throw new IndexOutOfBoundsException(Index: index);return new ListItr(index);}/***返回列表中的列表迭代器按适当的顺序。*返回的列表迭代器是fail-fast 。*/public ListIteratorE listIterator() {return new ListItr(0);}/***以正确的顺序返回该列表中的元素的迭代器。*返回的迭代器是fail-fast 。*/public IteratorE iterator() {return new Itr();} 3. ArrayList 扩容机制分析 3.1. 先从 ArrayList 的构造函数说起 JDK8ArrayList 有三种方式来初始化构造方法源码如下 /*** 默认初始容量大小*/private static final int DEFAULT_CAPACITY 10;private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA {};/***默认构造函数使用初始容量10构造一个空列表(无参数构造)*/public ArrayList() {this.elementData DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/*** 带初始容量参数的构造函数。用户自己指定容量*/public ArrayList(int initialCapacity) {if (initialCapacity 0) {//初始容量大于0//创建initialCapacity大小的数组this.elementData new Object[initialCapacity];} else if (initialCapacity 0) {//初始容量等于0//创建空数组this.elementData EMPTY_ELEMENTDATA;} else {//初始容量小于0抛出异常throw new IllegalArgumentException(Illegal Capacity: initialCapacity);}}/***构造包含指定collection元素的列表这些元素利用该集合的迭代器按顺序返回*如果指定的集合为nullthrows NullPointerException。*/public ArrayList(Collection? extends E c) {elementData c.toArray();if ((size elementData.length) ! 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() ! Object[].class)elementData Arrays.copyOf(elementData, size, Object[].class);} else {// replace with empty array.this.elementData EMPTY_ELEMENTDATA;}} 细心的同学一定会发现 以无参数构造方法创建 ArrayList 时实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时才真正分配容量。即向数组中添加第一个元素时数组容量扩为 10。 下面在我们分析 ArrayList 扩容时会讲到这一点内容 补充JDK7 new无参构造的ArrayList对象时直接创建了长度是10的Object[]数组elementData 。jdk7中的ArrayList的对象的创建类似于单例的饿汉式而jdk8中的ArrayList的对象的创建类似于单例的懒汉式。JDK8的内存优化也值得我们在平时开发中学习。 3.2. 一步一步分析 ArrayList 扩容机制 这里以无参构造函数创建的 ArrayList 为例分析 3.2.1. 先来看 add 方法 /*** 将指定的元素追加到此列表的末尾。*/public boolean add(E e) {//添加元素之前先调用ensureCapacityInternal方法ensureCapacityInternal(size 1); // Increments modCount!!//这里看到ArrayList添加元素的实质就相当于为数组赋值elementData[size] e;return true;}注意 JDK11 移除了 ensureCapacityInternal() 和 ensureExplicitCapacity() 方法 3.2.2. 再来看看 ensureCapacityInternal() 方法 JDK7可以看到 add 方法 首先调用了ensureCapacityInternal(size 1) //得到最小扩容量private void ensureCapacityInternal(int minCapacity) {if (elementData DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {// 获取默认的容量和传入参数的较大值minCapacity Math.max(DEFAULT_CAPACITY, minCapacity);}ensureExplicitCapacity(minCapacity);}当 要 add 进第 1 个元素时minCapacity 为 1在 Math.max()方法比较后minCapacity 为 10。 此处和后续 JDK8 代码格式化略有不同核心代码基本一样。 3.2.3. ensureExplicitCapacity() 方法 如果调用 ensureCapacityInternal() 方法就一定会进入执行这个方法下面我们来研究一下这个方法的源码 //判断是否需要扩容private void ensureExplicitCapacity(int minCapacity) {modCount;// overflow-conscious codeif (minCapacity - elementData.length 0)//调用grow方法进行扩容调用此方法代表已经开始扩容了grow(minCapacity);} 我们来仔细分析一下 当我们要 add 进第 1 个元素到 ArrayList 时elementData.length 为 0 因为还是一个空的 list因为执行了 ensureCapacityInternal() 方法 所以 minCapacity 此时为 10。此时minCapacity - elementData.length 0成立所以会进入 grow(minCapacity) 方法。当 add 第 2 个元素时minCapacity 为 2此时 e lementData.length(容量)在添加第一个元素后扩容成 10 了。此时minCapacity - elementData.length 0 不成立所以不会进入 执行grow(minCapacity) 方法。添加第 3、4···到第 10 个元素时依然不会执行 grow 方法数组容量都为 10。 直到添加第 11 个元素minCapacity(为 11)比 elementData.length为 10要大。进入 grow 方法进行扩容。 3.2.4. grow() 方法 /*** 要分配的最大数组大小*/private static final int MAX_ARRAY_SIZE Integer.MAX_VALUE - 8;/*** ArrayList扩容的核心方法。*/private void grow(int minCapacity) {// oldCapacity为旧容量newCapacity为新容量int oldCapacity elementData.length;//将oldCapacity 右移一位其效果相当于oldCapacity /2//我们知道位运算的速度远远快于整除运算整句运算式的结果就是将新容量更新为旧容量的1.5倍int newCapacity oldCapacity (oldCapacity 1);//然后检查新容量是否大于最小需要容量若还是小于最小需要容量那么就把最小需要容量当作数组的新容量if (newCapacity - minCapacity 0)newCapacity minCapacity;// 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) hugeCapacity() 方法来比较 minCapacity 和 MAX_ARRAY_SIZE//如果minCapacity大于最大容量则新容量则为Integer.MAX_VALUE否则新容量大小则为 MAX_ARRAY_SIZE 即为 Integer.MAX_VALUE - 8。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);}int newCapacity oldCapacity (oldCapacity 1),所以 ArrayList 每次扩容之后容量都会变为原来的 1.5 倍左右oldCapacity 为偶数就是 1.5 倍否则是 1.5 倍左右 奇偶不同比如 1010/2 15, 3333/249。如果是奇数的话会丢掉小数. “”移位运算符1 右移一位相当于除 2右移 n 位相当于除以 2 的 n 次方。这里 oldCapacity 明显右移了 1 位所以相当于 oldCapacity /2。对于大数据的 2 进制运算,位移运算符比那些普通运算符的运算要快很多,因为程序仅仅移动一下而已,不去计算,这样提高了效率,节省了资源 我们再来通过例子探究一下grow() 方法 当 add 第 1 个元素时oldCapacity 为 0经比较后第一个 if 判断成立newCapacity minCapacity(为 10)。但是第二个 if 判断不会成立即 newCapacity 不比 MAX_ARRAY_SIZE 大则不会进入 hugeCapacity 方法。数组容量为 10add 方法中 return true,size 增为 1。当 add 第 11 个元素进入 grow 方法时newCapacity 为 15比 minCapacity为 11大第一个 if 判断不成立。新容量没有大于数组最大 size不会进入 hugeCapacity 方法。数组容量扩为 15add 方法中 return true,size 增为 11。以此类推······ 这里补充一点比较重要但是容易被忽视掉的知识点 java 中的 length属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了 length 这个属性.java 中的 length() 方法是针对字符串说的,如果想看这个字符串的长度则用到 length() 这个方法.java 中的 size() 方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看! 3.2.5. hugeCapacity() 方法。 从上面 grow() 方法源码我们知道 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) hugeCapacity() 方法来比较 minCapacity 和 MAX_ARRAY_SIZE如果 minCapacity 大于最大容量则新容量则为Integer.MAX_VALUE否则新容量大小则为 MAX_ARRAY_SIZE 即为 Integer.MAX_VALUE - 8。 private static int hugeCapacity(int minCapacity) {if (minCapacity 0) // overflowthrow new OutOfMemoryError();//对minCapacity和MAX_ARRAY_SIZE进行比较//若minCapacity大将Integer.MAX_VALUE作为新数组的大小//若MAX_ARRAY_SIZE大将MAX_ARRAY_SIZE作为新数组的大小//MAX_ARRAY_SIZE Integer.MAX_VALUE - 8;return (minCapacity MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}3.3. System.arraycopy() 和 Arrays.copyOf()方法 阅读源码的话我们就会发现 ArrayList 中大量调用了这两个方法。比如我们上面讲的扩容操作以及add(int index, E element)、toArray() 等方法中都用到了该方法 3.3.1. System.arraycopy() 方法 /*** 在此列表中的指定位置插入指定的元素。*先调用 rangeCheckForAdd 对index进行界限检查然后调用 ensureCapacityInternal 方法保证capacity足够大*再将从index开始之后的所有成员后移一个位置将element插入index位置最后size加1。*/public void add(int index, E element) {rangeCheckForAdd(index);ensureCapacityInternal(size 1); // Increments modCount!!//arraycopy()方法实现数组自己复制自己//elementData:源数组;index:源数组中的起始位置;elementData目标数组index 1目标数组中的起始位置 size - index要复制的数组元素的数量System.arraycopy(elementData, index, elementData, index 1, size - index);elementData[index] element;size;}我们写一个简单的方法测试以下 public class ArraycopyTest {public static void main(String[] args) {// TODO Auto-generated method stubint[] a new int[10];a[0] 0;a[1] 1;a[2] 2;a[3] 3;System.arraycopy(a, 2, a, 3, 3);a[2]99;for (int i 0; i a.length; i) {System.out.print(a[i] );}}}结果 0 1 99 2 3 0 0 0 0 03.3.2. Arrays.copyOf()方法 /**以正确的顺序返回一个包含此列表中所有元素的数组从第一个到最后一个元素; 返回的数组的运行时类型是指定数组的运行时类型。*/public Object[] toArray() {//elementData要复制的数组size要复制的长度return Arrays.copyOf(elementData, size);}个人觉得使用 Arrays.copyOf()方法主要是为了给原有数组扩容测试代码如下 public class ArrayscopyOfTest {public static void main(String[] args) {int[] a new int[3];a[0] 0;a[1] 1;a[2] 2;int[] b Arrays.copyOf(a, 10);System.out.println(b.lengthb.length);} }结果 103.3.3. 两者联系和区别 联系 看两者源代码可以发现 copyOf()内部实际调用了 System.arraycopy() 方法 区别 arraycopy() 需要目标数组将原数组拷贝到你自己定义的数组里或者原数组而且可以选择拷贝的起点和长度以及放入新数组中的位置 copyOf() 是系统自动在内部新建一个数组并返回该数组。 3.4. ensureCapacity方法 ArrayList 源码中有一个 ensureCapacity 方法不知道大家注意到没有这个方法 ArrayList 内部没有被调用过所以很显然是提供给用户调用的那么这个方法有什么作用呢 /**如有必要增加此 ArrayList 实例的容量以确保它至少可以容纳由minimum capacity参数指定的元素数。** param minCapacity 所需的最小容量*/public void ensureCapacity(int minCapacity) {int minExpand (elementData ! DEFAULTCAPACITY_EMPTY_ELEMENTDATA)// any size if not default element table? 0// larger than default for default empty table. Its already// supposed to be at default size.: DEFAULT_CAPACITY;if (minCapacity minExpand) {ensureExplicitCapacity(minCapacity);}} 最好在 add 大量元素之前用 ensureCapacity 方法以减少增量重新分配的次数 我们通过下面的代码实际测试以下这个方法的效果 public class EnsureCapacityTest {public static void main(String[] args) {ArrayListObject list new ArrayListObject();final int N 10000000;long startTime System.currentTimeMillis();for (int i 0; i N; i) {list.add(i);}long endTime System.currentTimeMillis();System.out.println(使用ensureCapacity方法前(endTime - startTime));} }运行结果 使用ensureCapacity方法前2158public class EnsureCapacityTest {public static void main(String[] args) {ArrayListObject list new ArrayListObject();final int N 10000000;list new ArrayListObject();long startTime1 System.currentTimeMillis();list.ensureCapacity(N);for (int i 0; i N; i) {list.add(i);}long endTime1 System.currentTimeMillis();System.out.println(使用ensureCapacity方法后(endTime1 - startTime1));} }运行结果 使用ensureCapacity方法前1773通过运行结果我们可以看出向 ArrayList 添加大量元素之前最好先使用ensureCapacity 方法以减少增量重新分配的次数。
http://www.hkea.cn/news/14259992/

相关文章:

  • 重庆 手机网站制作培训机构网络推广方案
  • 黄冈网站建设有哪些wordpress的目录结构
  • 网站添加百度商桥企业邮箱号怎么注册
  • 做网站用什么编程电子设计网站
  • 网站seo哪家好成都模板网建站
  • 住房城乡建设部执业资格注册中心网站qq推广工具
  • 基层建设网站是不是停办了杭州有哪些性价比高的网站建设服务商
  • 无锡上海网站建设模板制作安装
  • 网站开发人员职责58招商加盟项目
  • 做视频网站成本高吗网站建设推广工资
  • 郑州模板网站制作直播视频下载
  • 网站制作详情windows2008 iis 网站配置
  • 绍兴cms建站模板网络营销管理名词解释
  • 网站自建设需要买什么时候开始咸阳网站开发
  • 桂林有名网站制作公司胶州哪家公司做网站
  • wordpress网站在线安装建设网站费用一般多少
  • 旅游电子商务网站建设规划方案wordpress渗透经验
  • 怎么把网站模板上传到自己的网站医疗网站建设网站
  • 集团网站下分网站 模板陕西app定制
  • 公司可以做多个网站吗怎么做网页漂亮
  • 公司网站推广现状番禺网站建设三杰科技
  • 桂林北站到阳朔中学生网站源码
  • 免费建立自己的网站空间网站整体地图怎么做
  • 互联网众筹网站怎样建设wordpress不能登录界面
  • 冻品网站的建设背景淘宝网站建设目标是什么意思
  • 怎么做一个摄影平台网seo营销技巧
  • 南京建设监理协会网站打不开网站排名技巧
  • 深圳市盐田区住房建设局网站做高端品牌生产商的网站
  • 无锡画室网站建设网站建设公司专业网站科技开发
  • 广州网站建设哪家技术好南昌网站建设公司如何