java List的4种实现类
java List的4种实现类
以下都是个人理解的描述
ArrayList
- ArrayList是我们在java开发过程中最常见的一种List实现类,属于线程不安全,读取速度快的一种List实现类。也是java入门时最常用的实现类。
- 其中最重要的三个参数即如下代码所示,初始数组增量和一个数组
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final int DEFAULT_CAPACITY = 10; transient Object[] elementData; private int size; ... }
- 因为ArrayList采用的是数组的方式实现,所以其取值速度快,插入碰到扩容问题时速度会减慢,主要原因可以看如下代码
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { modCount++; if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
初始化:
1.初始化数组长度,小于零就抛出异常,传0则与不传参是一样的
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
2.Collection子类初始化,存在空指针风险,数据利用Array.copyOf进行拷贝
public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { this.elementData = EMPTY_ELEMENTDATA; } }
3.无参初始化,就是赋予一个空数组,利用扩容做初始化长度
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
最大数组长度:
0x7fff ffff(即Integer的最大长度)或0x7fff ffff – 8
数组增长:
第一次默认增长10,一般情况下向右位移一1位,即以每次以当前数据长度的0.5倍增长
当数组长度达到临界点,增长超过了0x7fff ffff -8时,数组最大长度为0x7fff ffff
sort方法:
利用Array中采用的TimSort二分归并排序方法,注意实现 Comparable接口推荐区分1,-1,0三种情况
Vector
和ArrayList基本相似,利用数组及扩容实现List,但Vector是一种线程安全的List结构,它的读写效率不如ArrayList,其原因是在该实现类内在方法上加上了同步关键字,如
public synchronized E get(int index) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index); }
其不同之处还在于Vector的增长速度不同,如下
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } private void ensureCapacityHelper(int minCapacity) { if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
可以看出Vector在默认情况下是以两倍速度递增
所以capacityIncrement可以用来设置递增速度,因此Vector的初始化多了一种方式,即设置数组增量
public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement; } public Vector(int initialCapacity) { this(initialCapacity, 0); } public Vector() { this(10); }
LinkedList
- LinkedList是利用内部类Node为数据单元的双向链表,同样LinkedList是线程不安全的,其具有读效率低,写效率高,操作效率高等特性,适合用于频繁add,remove等操作的List,同时可以节省一定的内存,在clear的情况下推荐使用GC回收,并且没有最大长度限制。
- 可以看出双向链表的节点操作没有扩充的拷贝操作,在这种情况下操作相对于反复扩容效率要高,但也仅是相对的,但是有大量数据操作,特别是删除等,只需要做节点的横向移动,效率是很高的。
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { transient int size = 0; transient Node<E> first; transient Node<E> last; public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } public boolean remove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; } ... }
当然LinkedList没有预留排序接口
Stack
- 继承于Vector,基本特性与Vector一致,线程安全,但效率低,实际就是利用Vector抽象成栈,使之拥有后进先出的特性
PS.
二分归并算法:
就是通过二分的方式将问题拆分到原子问题,然后通过问题的解决和归并,进行排序,例如将一组随机数拆分利用二分法拆分成多组进行排序,合并时排序,合并完成后,排序也就完成了
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
使用Lambda表达式与回调函数简化缓存操作
1. 缓存操作流程 对一些写低频,读高频的数据操作我们经常需要用到缓存,通常的缓存操作流程如下: 2. 通常的缓存处理方式 通常我们对上面流程的实现,伪代码如下: public Object getObject(String key) { //1. 尝试从缓存读取 Object obj = readFromCache(key); //缓存命中直接返回 if (obj != null) { return obj; } //2.如果缓存未命中,读数据库 obj = readFromDB(); //3. 回写入缓存,并返回 saveToCache(key,obj); return obj; } 对于不同缓存的处理上面步骤1、3是重复的,步骤2是取决
- 下一篇
java EasyExcel集成及工具类使用
EasyExcel简介 easyExcel是阿里巴巴开源poi插件之一,当前最新版本1.1.2-beta5,poi版本3.17,因此,集成时老版本poi需要提升poi版本,或者做版本隔离。 吐槽一下这个版本没有RELEASE版本 主要解决了poi框架使用复杂,sax解析模式不容易操作,数据量大起来容易OOM,解决了POI并发造成的报错 主要解决方式:通过解压文件的方式加载,一行一行的加载,并且抛弃样式字体等不重要的数据,降低内存的占用 具体实现原理,建议看github上的readme EasyExcel优势 注解式自定义操作。 输入输出简单,提供输入输出过程的接口 支持一定程度的单元格合并等灵活化操作 EasyExcel劣势 框架不成熟,1.1.0版本后提供灵活接口的只剩beta版本 依然存在一些bug 没有一套完整的api ExcelUtil快速使用 maven引用(版本控制内若存在低版本POI,请升级版本和代码,官方POI版本3.17): <dependency> <groupId>com.alibaba</groupId> <artifa...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- Red5直播服务器,属于Java语言的直播服务器
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS6,7,8上安装Nginx,支持https2.0的开启