ArrayList动态增长方式
来源:互联网 发布:网络刷手一天能挣多少 编辑:程序博客网 时间:2024/05/22 08:21
ArrayList动态增长方式
ensureCapacityInternal-> ensureExplicitCapacity->grow-> hugeCapacity
- ensureCapacityInternal:判断数组是否非空,若为空,比较DEFAULT_CAPACITY(ArrayList默认容量为10)与minCapacity设最大值为容量值
- ensureExplicitCapacity:modCount++,若minCapacity大与数组长度时调用grow扩容
- grow扩容原数组长度50%,与minCapacity比较取最大值,若最终取值大与MAX_ARRAY_SIZE,调用hugeCapacity最大容量函数扩容
注:上两步的比较均采用相减与0比较的方式,针对最大值溢出Integer.MAX_VALUE为负的情况 - hugeCapacity判断容量值是否<0(若int值大与Integer.MAX_VALUE,则内存溢出),是则抛出OOM异常。设最终容量为(minCapacity >MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;
注:试图分配更大数组时可能导致OutOfMemoryError:被请求数组的size超出VM界限 - grow调用Arrays.copyOf()复制数组
总结:
分配次数
1千需要分配 11次
1万一级需要分配17次
10万 需要分配23次
100万需要分配28次
因扩容为自增0.5倍,为避免不必要的内存泄漏,应该考虑用ensureCapacity方法
申请扩容(大与DEFAULT_CAPACITY)的四种结果:
1. 原容量的1.5倍
2. 用户自定义minCapacity值
3. MAX_ARRAY_SIZE(等于Integer.MAX_VALUE-8)
4. Integer.MAX_VALUE
补充相关小知识点:
1.前面grow方法中为什么要采用相减与0比较的方式
public static void main(String[] args) { // Integer的取值范围-2147483648 ~ 2147483647 (-2^31 ~ 2^31-1) int i = Integer.MAX_VALUE + 1; int max = Integer.MAX_VALUE; int min = Integer.MIN_VALUE; System.out.println(i > max-8);// false System.out.println(i - max > 0);// true System.out.println(min == i);// true System.out.println(min == i);// true arraytest();}
2.Arrays.copyof(···)与System.arraycopy(···)方法比较
//Arrays.copyof方法public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { T[] copy = ((Object)newType == (Object)Object[].class)//判断是否为Object类型 ? (T[]) new Object[newLength]//若为Object类型生成一个Object数组 : (T[]) Array.newInstance(newType.getComponentType(), newLength); //否则生成一个newType数组类型的数组 //Class.getComponentType():返回表示数组组件类型的 Class。如果此类不表示数组类,则此方法返回 null。 System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy;}//System.arraycopy方法public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
总结:
System.arraycopy可以指定复制目标数组与起始复制位置。嗯~思考一下作用:可以实现向数组中部插入删除耶~
而Arrays.copyof只是返回一个新数组,只能复制原数组从0到newLength的值,内部调用System.arraycopy实现
3.关于MAX_ARRAY_SIZE
/** * The maximum size of array to allocate. * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
这个为什么要取一个Integer.MAX_VALUE - 8呢?
- 原注释提到说这块区域是为了存放一些头数据
- 其实也是为了避免一些机器内存溢出,-8 是为了减少出错的几率
- 数组的长度太大了,会导致JVM内存溢出,所以当你的内存足够大时,数组的扩容接近内存的最大值时,数组不会直接扩满,还会留一些空间(8这一个字节),保证这时候JVM还能有些内存空间去做GC,清除其他不用的内存来缓冲
关于这个问题的答案,保留个人想法,欢迎大家指正错误
0 0
- ArrayList动态增长方式
- ArrayList长度增长方式
- java 1.8 ArrayList容量增长方式
- jdk 1.7中 ArrayList的容量增长方式
- ArrayList集合容量增长
- ArrayList,List等非链式线性结构是如何实现动态增长的
- 数据库的增长方式
- vector内存增长方式
- StringBuffer增长方式
- vector内存增长方式
- 关于ArrayList和Vector的自动增长
- vector的capacity增长方式
- arm堆栈的增长方式
- arm堆栈的增长方式
- vector的capacity增长方式
- 堆栈地址空间增长方式
- C++ 的Vector增长方式
- Vector的自增长方式
- bzoj3432
- Java项目中读取properties文件
- 【高性能JavaScript】读书笔记
- 【Spring MVC】深度探险SpringMVC(二)——框架介绍
- CSS单位
- ArrayList动态增长方式
- gplt L2-006. 树的遍历(后序中序求层序)
- 定位消耗CPU最多的线程
- TensorFlow用到的数学知识传送门
- className ~
- easyUI datagrid 遍历集合
- 关联规则算法1------关联规则Apriori原理和R实现
- 事务的四种隔离级别
- dpdk学习之一--初识dpdk