arraylist源码 -ag凯发k8国际
实现了 randomaccess 接口,因此支持随机访问。这是理所当然的,因为arraylist 是基于数组实现的。
数组的默认大小为 10。
private static final int default_capacity = 10;arraylist基于数组实现,并且具有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就没必要全部进行序列化。
保存元素的数组elementdata使用transient修饰,该关键字声明数组默认不会被序列化。
transient object[] elementdata; // non-private to simplify nested class accessarraylist 实现了writeobject() 和 readobject() 来控制只序列化数组中有元素填充那部分内容。
private void readobject(java.io.objectinputstream s) throws java.io.ioexception, classnotfoundexception {elementdata = empty_elementdata;// read in size, and any hidden stuffs.defaultreadobject();// read in capacitys.readint(); // ignoredif (size > 0) {// be like clone(), allocate array based upon size not capacityensurecapacityinternal(size);object[] a = elementdata;// read in all elements in the proper order.for (int i=0; i而 writeobject() 方法在传入的对象存在 writeobject() 的时候会去反射调用该对象的 writeobject() 来实现序列化。
反序列化使用的是 objectinputstream 的readobject() 方法,原理类似。
arraylist list = new arraylist(); objectoutputstream oos = new objectoutputstream(new fileoutputstream(file)); oos.writeobject(list);添加元素时使用 ensurecapacityinternal() 方法来保证容量足够,如果不够时,需要使用 grow() 方法进行扩容,新容量的大小为 oldcapacity (oldcapacity>> 1) ,也就是旧容量的 1.5 倍。
扩容操作需要调用 arrays.copyof() 把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 arraylist 对象时就指定大概的容量大小,减少扩容操作的次数。
public boolean add(e e) {ensurecapacityinternal(size 1); // increments modcount!!elementdata[size ] = e;return true; } 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(mincapacity); } private void grow(int mincapacity) {// overflow-conscious codeint oldcapacity = elementdata.length;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); }需要调用 system.arraycopy() 将 index 1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 o(n),可以看出 arraylist 删除元素的代价是非常高的。
public e remove(int index) {rangecheck(index);modcount ;e oldvalue = elementdata(index);int nummoved = size - index - 1;if (nummoved > 0)system.arraycopy(elementdata, index 1, elementdata, index, nummoved);elementdata[--size] = null; // clear to let gc do its workreturn oldvalue; }modcount 用来记录 arraylist 结构发生变化的次数。
- 结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。
在进行序列化或者迭代等操作时,需要比较操作前后 modcount 是否改变,如果改变了需要抛出 concurrentmodificationexception。
private void writeobject(java.io.objectoutputstream s)throws java.io.ioexception{// write out element count, and any hidden stuffint expectedmodcount = modcount;s.defaultwriteobject();// write out size as capacity for behavioural compatibilitywith clone()s.writeint(size);// write out all elements in the proper order.for (int i=0; i总结
以上是ag凯发k8国际为你收集整理的arraylist源码的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 容器(collection/map)、容
- 下一篇: