ArrayList底层几个注意的点

1、elementData 被transient关键字修饰的原因

    大家知道transient关键字的意思,简单的说就是被这个关键字修饰的属性是不会被序列化和反序列化的。当一个类的一个成员变量被这个关键字修饰,当对象序列化存储在硬件里,又反序列化取出时,那个修饰的变量会显示“NOT SET”,大家可以去验证一下,这里不多解释。那arrayList中的elementData 为什么被这个关键字修饰呢?难道不需要这个属性序列化吗?其实是这样的,一个arrayList的容量一般是比它的size要大的,比方我的容量是10,但的存进去的值就只有3,也就是size()只有3.那如果elementData 不被transient修饰的话,就相当于整个容量为10的list全部被序列化了,那我们知道其实list里面就只有3个有效值,其它都是空的,这样会造成资源浪费。那怎么做呢?transient就发挥作用的,那个变量修饰为transient,使其不能被序列化。那有的人会问,那不是那三个有效值也不能序列化了。不是的,arrayList提供了一个方法writeObject,大家可以去看一下源码,我下午看了一下,它的代码是先序列化除了被transient修饰的其它东西,再循环elementData ,将其有值的序列化,反序列化也同样有一个方法的。

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();
    }
}

2、arrayList的trimtosize方法

比方有一个list,容量大小为10,但只放5个元素,当这个list执行trimtosize方法后,list会删除其它5个没有放元素的内存空间


3、arrayList再扩容的时候是重新生成对象还是在原来的list里面扩建?

arrayList的扩容是根据一定的扩容机制,用Arrays.copyOf创建扩容之后的一个新对象,原先的内容也直接复制在新对象里面

示例图如下:

4、为什么arrayList的插入,删除性能为变差的原因

这里我以arrayList的插入为例,示例图如下

public static void main(String[] args)
{
    List<String> list = new ArrayList<String>();
    list.add("111");
    list.add("222");
    list.add("333");
    list.add("444");
    list.add("555");
    list.add("666");
    list.add("777");
    list.add("888");
    list.add(2, "000");
    System.out.println(list);
}



看一下插入的源码

public void add(int index, E element) {
if (index > size || index < 0)
    throw new IndexOutOfBoundsException(
    "Index: "+index+", Size: "+size);
    ensureCapacity(size+1);  // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
         size - index);
elementData[index] = element;
size++;
}

结合图,简单的是插入的原理就是先用System.arraycopy方法将你要插入位置之后的元素复制一份,以及往后移动一位,之后再要插入的地方插入数据。 System.arraycopy和copyOf方法有不一样的地方,System.arraycopy是可以复制到原先的那个对象的,也就是可以不产生新对象。删除同理。插入,删除元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值