arraylist,与linkedlist:vector区别

参考:

源码浅析ArrayList、LinkedList和Vector的区别

集合初始容量(DEFAULT_CAPACITY)加载因子(DEFAULT_LOAD_FACTOR)扩容增量
ArrayList101:即当 元素个数 超过 [容量长度] 时,进行扩容原容量的 0.5倍+1 ,如 ArrayList 的容量为10,一次扩容后是容量为16
HashMap16,是2^4 或 1 << 4,可以提高查询效率0.75:即当 元素个数 超过 [容量长度的0.75倍] 时,进行扩容原容量的 1 倍 , 容量为16,一次扩容后是容量为32

一、ArrayList和LinkedList的区别

从实现看:

  • LinkedList底层实现是双向链表
  • ArrayList底层实现是动态数组

从扩容机制看:

  • LinkedList不存在扩容 的说法,因为是链表结构。

  • ArrayList底层是动态数组存在扩容说法,默认的数组大小是10,在检测是否需要扩容后,如果扩容,会扩容为原来的1.5倍大小。原理就是把老数组的元素存储到新数组里面

从优点看:

  • ArrayList的查找性能好,因为底层是数组,适用于查找元素。

  • LinkedList底层是双链表,对于插入或者删除元素来说,操作方便,性能高。

对于随机访问,ArrayList优于LinkedList, 对于插入和删除操作,LinkedList优于 ArrayList

从缺点看:

  • ArrayList因为是一块连续的内存,存储数据元素,所以如果要删除或者插入一个元素,那么之前或者之后的元素都要移动,代价很高。

  • LinkedList是链表,在内存中可以是不连续的,通过指针连接结点,如果要查找元素,必须去遍历整个链表,这样就比较麻烦。

LinkedListArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。

从安全角度看:

  • ArrayList在单线程环境下是安全的,多线程环境下不是线程安全的,容易造成脏读的问题,如果要使ArrayList是线程安全的,那么可以选择使用Collections.synchronizedList(new ArrayList())

  • LinkedList在单线程环境下是安全的,多线程环境下不是线程安全的,容易造成脏读的问题,如果要使LinkedList是线程安全的,那么可以选择使用Collections.synchronizedList(new LinkedList())

LinkedList和ArrayList的数据存储都是有序的,而且元素是可以重复的。

两者add都是将元素追加到现有集合元素的末尾。

二、ArrayList源码:


public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

    //初始默认容量
    private static final int DEFAULT_CAPACITY = 10;

    private static final Object[] EMPTY_ELEMENTDATA = {};
	
    transient Object[] elementData;

    //实际有多少元素
    private int size;
	
	//最大容量:默认为 10,最大容量为 int 上限,减 8 是为了容错
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

	//.........构造方法.......
	
	 public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }

    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
	
	
	//........................
	public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;//在数组末尾追加一个元素,并修改size
        return true;
    }
	
    private void ensureCapacityInternal(int minCapacity) {
		//利用 == 可以判断数组是否是用默认构造函数初始化的
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//如果确定要扩容,会修改modCount 

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }	
	
	//需要扩容的话,默认扩容一半
	private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//默认扩容一半
        if (newCapacity - minCapacity < 0)//如果还不够 ,那么就用 能容纳的最小的数量。(add后的容量)
            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);//拷贝,扩容,构建一个新数组,
    }
	

ArrayList 底层基于【数组】实现容量大小动态可变。

扩容机制为首先扩容为原始容量的 1.5 倍。

如果1.5倍太小的话,则将我们所需的容量大小赋值给 newCapacity,

如果1.5倍太大或者我们需要的容量太大,那就直接拿 newCapacity = (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE 来扩容。

扩容之后是通过数组的拷贝来确保元素的准确性的,所以尽可能减少扩容操作。

elementData.length 为数组长度,表示最多可以存储多少个元素。

如果需要边遍历边 remove ,必须使用 iterator。且 remove 之前必须先 next,next 之后只能用一次 remove。

三、ArrayList 的增加或删除操作相对来说效率比较低

ArrayList 在小于扩容容量的情况下其实增加操作效率是非常高的,在涉及扩容的情况下添加操作效率确实低,删除操作需要移位拷贝,效率是低点。

因为 ArrayList 中增加(扩容)或者是删除元素要调用 System.arrayCopy 这种效率很低的方法进行处理,

所以如果遇到了数据量略大且需要频繁插入或删除的操作效率就比较低了,具体可查看 ArrayList 的 add 和 remove 方法实现,

但是 ArrayList 频繁访问元素的效率是非常高的,因此遇到类似场景我们应该尽可能使用 LinkedList 进行替代效率会高一些的。

四、arraylist:linkedlist:vector区别:

在这里插入图片描述

ArrayList

ArrayList就是【动态数组】
它允许所有元素,包括null。
ArrayList并不是线程安全的
其底层使用数组保存所有元素所以其操作基本上是对数组的操作。
在对 ArrayList 中存储元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,如果超出,数组将会进行扩容,扩容原来的一半,以满足添加数据的需求。

LinkedList

LinkedList 是一个继承于AbstractSequentialList的【双向链表】。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,能对它进行队列操作,允许null元素。
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
LinkedList 是非同步的,即非线程安全的,一种解决方法是在创建List时构造一个同步的List:List list = Collections.synchronizedList(new LinkedList(…));
LinkedList是通过节点直接彼此连接来实现的。每一个节点都包含前一个节点的引用,后一个节点的引用和节点存储的值。当一个新节点插入时,只需要修改其中保持先后关系的节点的引用即可,当删除记录时也一样。
LinkedList相对于ArrayList来说,是可以快速添加,删除元素,ArrayList添加删除元素的话需移动数组元素,可能还需要考虑到扩容数组长度。

Vector

Vector非常类似ArrayList,是可实现自动增长的对象【数组】。是有序的,可以重复的
Vector在所有的方法上面都加了synchronized 关键字。虽然其都使用了synchronized 关键字修饰,对于单操作而言是线程安全的,但是如果是组合操作,就需要我们另行同步处理。
Vector是fail-fast机制
Vector也需要进行扩容,Vector默认增长为原来一倍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ArrayListLinkedListVector都是Java集合框架中的List接口的实现类,它们之间有一些区别。 1. 数据结构:ArrayListVector都是基于数组实现的,而LinkedList是基于双向链表实现的。 2. 线程安全性:ArrayListLinkedList是非线程安全的,而Vector是线程安全的。这意味着在多线程环境中,如果需要对集合进行修改操作,使用Vector会更安全,而对于单线程环境,ArrayListLinkedList的性能更好。 3. 扩容机制:ArrayListVector都具有自动扩容的能力,当集合中的元素数量超过当前容量时,它们会重新分配内存空间来容纳更多的元素。但是,ArrayList每次扩容时将当前容量增加一半,而Vector则将当前容量翻倍。LinkedList则不需要扩容,因为它的元素是通过链表连接起来的。 4. 遍历效率:ArrayList的遍历效率最高,因为它是基于数组实现的,可以直接根据索引获取元素;LinkedList的遍历效率较低,因为需要遍历链表中的每个节点;Vector的遍历效率介于两者之间。 5. 插入和删除操作:ArrayList在尾部插入和删除元素的效率较高,因为它无需移动其他元素;LinkedList在任意位置插入和删除元素的效率较高,因为只需要修改链表中节点的指针;Vector的插入和删除操作效率较低,因为可能需要移动其他元素来保持连续性。 综上所述,选择使用哪个集合类取决于具体的需求和场景。如果需要高效的随机访问和修改操作,并且不涉及多线程环境,可以选择ArrayList;如果需要频繁的插入和删除操作,或者在多线程环境中使用,可以选择LinkedList;如果需要线程安全性,可以选择Vector
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值