彻底搞懂ArrayList和LinkedList集合类(1)

本文详细分析了ArrayList和LinkedList两种Java集合类的特性,包括接口说明、存取数据的方法以及效率。ArrayList适合于尾部添加和查询,而LinkedList在中间插入和删除上更优。同时,两者在遍历效率上各有优势。
摘要由CSDN通过智能技术生成

对于那些说ArrayList查询快、删除和添加效率低,以及LinkedList删除和添加效率高、但是查询效率低,我表示不认同,要具体问题具体分析,接下来具体分析ArrayList和LinkedList的区别。

1.ArrayList具体分析

在这里插入图片描述

(1)首先对于list接口说明:

List接口存储元素时可以重复、并且是有序的。
例如:在数组中存取【1,2,1,2】,在遍历时输出也是该样子。

(2)RandomAccess接口的说明:

RandomAccess它是一个标识接口,该接口中没有任何的方法以及属性。它的作用是支持快速的访问机制(即不需要遍历,根据索引值直接访问该索引下的内存地址值);例如以下get(int index)方法。

public interface RandomAccess {
}
//随机访问方法
public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

(3)Cloneable接口说明

Cloneable接口也是一个标识接口,作用是用来克隆ArrayList的,具体的实现是通过实现Object类中的clone方法类拷贝ArrayList中的数组值。

public interface Cloneable {
}
// 这是Object类中的clone方法
protected native Object clone() throws CloneNotSupportedException;
//这是ArrayList的具体实现
public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

通过以上的方法可以分析出ArrayList在拷贝时,是拷贝的数组的具体有多少个值即(size),而并非是数组的整个容量。这样可以节约拷贝的效率以及节省空间。

(4)Serializable 接口的说明

该接口也是一个标识接口,实现该接口表示该类可以进行序列化与反序列化。

public interface Serializable {
}

通过分析ArrayList的源码,可以看书存储数据的数组使用transient Object[] elementData;进行修饰,那么Serializable支持序列化与反序列化,但是transient修饰的数据不允许序列化与反序列化,那么岂不是矛盾了?如果不矛盾?那么ArrayList是如何解决该问题?

虽然说elementData采用了transient修饰,不能进行序列化与反序列化,但是ArrayList提供了writeObject以及readObject的方法来实现序列化与反序列化的,并且该方法提供了高效的方式来实现;假如数组的大小为15,只存储了10个数据,如果不进行transient修饰,直接序列化与反序列化,那么岂不是在这个过程中有五个是无效的数据。这只是5个,假如数据量特别大时,空余数量比较多,那么效率比较低,而对于writeObject和readObject方法只是序列化与反序列化具体的size大小个数据,从而提高了效率。

private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        int expectedModCount = modCount;
        s.defaultWriteObject();
        // Write out size as capacity for behavioural compatibility with clone()
        s.writeInt(size);
        // Write out all elements in the proper order.
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

(5)分析ArrayList是如何存取数据的

通过下面的构造函数可以看出ArrayList是采用Object类型的数组存储数据的。ArrayList在初始化时,如果采用有参构造函数,那么数组的容量为该有参构造函数的形式参数值;如果采用无参构造函数,那么该数组采用空数组。如果采用空数组那么何时进行扩容操作?

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
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: "+
           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值