ArrayList和Vector的扩容机制
ArrayList和Vector都是继承了相同的父类和实现了相同的接口。如下
- public class Vector<E>
- extends AbstractList<E>
- implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- {}
- public class ArrayList<E> extends AbstractList<E>
- implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- {}
两者之间我认为主要有两个却别。
1、Vector中的public方法都添加了synchronized关键字,以确保方法同步。
2、内部属性不同,这也是导致扩容方式不同的原因所在。
我现在来说第二条,
ArrayList有两个属性,存储数据的数组elementData,和存储记录数目的size。
Vector有三个属性,存储数据的数组elementData,存储记录数目的elementCount,还有扩展数组大小的扩展因子capacityIncrement。
先来看ArrayList的扩展方法
- public void ensureCapacity(int minCapacity) {
- modCount++;//父类中的属性,记录集合变化次数
- int oldCapacity = elementData.length;
- if (minCapacity > oldCapacity) {
- Object oldData[] = elementData;
- int newCapacity = (oldCapacity * 3)/2 + 1;
- if (newCapacity < minCapacity)
- newCapacity = minCapacity;
- elementData = (E[])new Object[newCapacity];
- System.arraycopy(oldData, 0, elementData, 0, size);
- }
- }
重构下看起来更方便
- public void ensureCapacity(int minCapacity) {
- modCount++;//父类中的属性,记录集合变化次数
- int oldCapacity = elementData.length;
- if (minCapacity > oldCapacity) {//扩容的条件,数组需要的长度要大于实际长度
- Object oldData[] = elementData;
- int newCapacity = ((oldCapacity * 3)/2 + 1)<minCapacity?minCapacity: ((oldCapacity * 3)/2 + 1);
- elementData = (E[])new Object[newCapacity];
- System.arraycopy(oldData, 0, elementData, 0, size);
- }
- }
可以看到,再满足扩容条件时,扩展后数组大小为((原数组长度*3)/2+1)与传递参数中较大者
再看看Vector的扩容方法
- public synchronized void ensureCapacity(int minCapacity) {
- modCount++;//父类中的属性,记录集合变化次数
- ensureCapacityHelper(minCapacity);
- }
- private void ensureCapacityHelper(int minCapacity) {
- int oldCapacity = elementData.length;
- if (minCapacity > oldCapacity) {//扩容的条件,数组需要的长度要大于实际长度
- Object[] oldData = elementData;
- int newCapacity = (capacityIncrement > 0) ?
- (oldCapacity + capacityIncrement) : (oldCapacity * 2);
- if (newCapacity < minCapacity) {
- newCapacity = minCapacity;
- }
- elementData = new Object[newCapacity];
- System.arraycopy(oldData, 0, elementData, 0, elementCount);
- }
- }
可以看到,相对于ArrayList的扩容方法,这个方法被一分为2,老实说我更喜欢这样,方法的职责更加明确。
int newCapacity = (capacityIncrement > 0) ?(oldCapacity + capacityIncrement) : (oldCapacity * 2);
当扩容因子大于0时,新数组长度为原数组长度+扩容因子,否子新数组长度为原数组长度的2倍。
if (newCapacity < minCapacity) {newCapacity = minCapacity;}
将上面生成的新数组长度与传递的参数要求长度作比较,较大者为最终的新长度。
ArrayList和Vector的扩容机制的更多相关文章
- 关于ArrayList的扩容机制
关于ArrayList的扩容机制 ArrayList作为List接口常用的一个实现类,其底层数据接口由数组实现,可以保证O(1) 复杂度的随机查找, 在增删效率上不如LinkedList,但是在查询效 ...
- java集合专题 (ArrayList、HashSet等集合底层结构及扩容机制、HashMap源码)
一.数组与集合比较 数组: 1)长度开始时必须指定,而且一旦指定,不能更改 2)保存的必须为同一类型的元素 3)使用数组进行增加/删除元素-比较麻烦 集合: 1)可以动态保存任意多个对象,使用比较方便 ...
- 浅谈JAVA中HashMap、ArrayList、StringBuilder等的扩容机制
JAVA中的部分需要扩容的内容总结如下:第一部分: HashMap<String, String> hmap=new HashMap<>(); HashSet<Strin ...
- ArrayList、Vector、HashMap、HashSet的默认初始容量、加载因子、扩容增量
当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使效率大大降低. 加载因 ...
- ArrayList、Vector、HashMap、HashTable、HashSet的默认初始容量、加载因子、扩容增量
这里要讨论这些常用的默认初始容量和扩容的原因是: 当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全 ...
- ArrayList源码解析(二)自动扩容机制与add操作
本篇主要分析ArrayList的自动扩容机制,add和remove的相关方法. 作为一个list,add和remove操作自然是必须的. 前面说过,ArrayList底层是使用Object数组实现的. ...
- ArrayList的扩容机制
一.ArrayList的扩容机制 1.扩容的计算方式是向右位移,即:newSize = this.size + (this.size>>1).向右位移,只有在当前值为偶数时,才是除以2:奇 ...
- 【数组】- ArrayList自动扩容机制
不同的JDK版本的扩容机制可能有差异 实验环境:JDK1.8 扩容机制: 当向ArrayList中添加元素的时候,ArrayList如果要满足新元素的存储超过ArrayList存储新元素前的存储能力, ...
- Java ArrayList自动扩容机制
动态扩容 1.add(E e)方法中 ① ensureCapacityInternal(size+1),确保内部容量,size是添加前数组内元素的数量 ② elementData[size++] ...
随机推荐
- 函数式编程语言LISP,python,haskell,clojure
说说我自己的背景吧,我是个半吊子的程序员,做任何事情喜欢比较了解然后再尝试,我接触过很多语言,大多数都把它当成工具来使用 我现在的工作大部分主要在于数据挖掘与机器学习方面,也学习web开发,我第一个拿 ...
- java发展史与java的语言特性
概述: Java 体系比较庞杂,功能繁多,这也导致很多人在自学 Java 的时候总是感觉无法建立 全面的知识体系, 无法从整体上把握Java 的原因. 在这里我们先简单了解一下Java 的版本. 具体 ...
- 遍历进程活动链表(ActiveProcessLinks)、DKOM隐藏进程
1.EPROCESS结构体 EPROCESS块来表示.EPROCESS块中不仅包含了进程相关了很多信息,还有很多指向其他相关结构数据结构的指针.例如每一个进程里面都至少有一个ETHREAD块表示的线程 ...
- 内核函数KiFastCallEntry
KiFastCallEntry() 机制分析 概述 Win32 子系统 API 调用 ntdll!ZwWriteFile() 函数 ntdll!KiFastSystemCall() 函数 _KUSER ...
- SQLServer 维护脚本分享(10)索引
--可添加索引的字段 migs.user_seeks,migs.avg_total_user_cost,migs.avg_user_impact,migs.last_user_seek ,mid.st ...
- Android Fragment学习笔记(二)----Fragment界面添加和管理
Fragment界面添加 了解过fragment的生命周期等简单知识,于是去看官方文档来了解更多相关内容,要添加fragment到我们的UI界面中,给出了两种常用的方法,第一个是在activity的布 ...
- POJ 2464 Brownie Points II(树状数组)
一开始还以为对于每根竖线,只要与过了任意一点的横线相交都可以呢,这样枚举两条线就要O(n^2),结果发现自己想多了... 其实是每个点画根竖线和横线就好,对于相同竖线统计(一直不包含线上点)右上左下总 ...
- Liferay 6.2 改造系列之三:删除Docbar中的添加内容功能
在/portal-master/portal-web/docroot/html/portlet/dockbar/add_panel.jsp文件中 将以下内容: if (hasAddContentAnd ...
- jQuery-品牌列表案例
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 表格边框css
table标签默认是没有边框的,但是如果我们自己加上边框boder:1px solid black;只有整个表格最外面有边框,那么如何给表格添加样式使得整个表格的tr.td都具有边框呢: <st ...