ToB企服应用市场:ToB评测及商务社交产业平台
标题:
2-ArrayList底层布局和源码分析
[打印本页]
作者:
伤心客
时间:
2024-7-12 09:19
标题:
2-ArrayList底层布局和源码分析
2-ArrayList底层布局和源码分析
介绍汇总:
ArrayList的注意事项
ArrayList的运行重要步骤
补充
1-ArrayList的注意事项
ArrayList
允许添加所有的元素
,包罗
null
,而且还可以多个
null
。
ArrayList 是由
数组
来实现数据存储的。
ArrayList 基本等同于 Vector
,除了 ArrayList 是
线程不安全
(
执行服从高
)看源码。
在多线程环境下,不建议使用 ArrayList。
// 此为 ArrayList 的 插入数据的方法
// 该方法并没有关键字 synchronized 修饰,可以表明 ArrayList 是线程不安全的
// synchronized 大概是加锁的意思
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
复制代码
2-ArrayList的运行重要步骤
ArrayList 中维护了一个 Object 范例的数组 elementData 。(debug 看源码
transient Object[] elementData;
// 先来解释 transient 关键字
/*
在Java中,transient关键字是一个变量修饰符,用来表示一个字段不应该被序列化。
当一个对象被序列化时(比如,通过ObjectOutputStream),对象的所有变量都会被写入到序列化文件中,
除了那些用transient修饰的变量。这样,当对象被反序列化时(比如,通过ObjectInputStream),
transient变量将不会被恢复,它们的值将会是类型的默认值(比如,int的默认值是0,
对象的默认值是null)。
*/
/*
transient关键字主要用于以下情况:
敏感信息:如果对象的某个字段包含敏感信息,如密码或个人身份识别信息,那么应该使用transient修饰该字段,以防止这些信息被序列化到文件中。
无法序列化的对象:如果对象的某个字段引用了另一个无法序列化的对象,那么这个字段也应该用transient修饰,否则序列化过程将抛出NotSerializableException异常。
派生字段:如果对象的某个字段的值可以从其他字段派生出来,那么该字段可以用transient修饰,以节省序列化和反序列化的时间和空间。
*/
// 解释一下 elementData 的作用
/*
在 Java 的 ArrayList 类中,transient Object[] elementData; 是一个非常重要的成员变量,它用于存储 ArrayList 中的元素。
ArrayList 是一个动态数组,能够根据需要自动扩容以存储更多的元素,而 elementData 就是用来实际存储这些元素的数组。
transient 关键字在这里的作用是阻止 elementData 数组被自动序列化。
由于 ArrayList 实现了 Serializable 接口,它支持序列化操作,
但是 elementData 数组中的元素可能包含不应该被序列化的数据,
或者数组本身的大小(容量)可能远大于实际存储的元素数量,导致序列化后的数据包含大量无用信息。
因此,ArrayList 提供了两个私有方法 writeObject(java.io.ObjectOutputStream s) 和 readObject(java.io.ObjectInputStream s) 来控制序列化和反序列化的过程。
在序列化时,writeObject 方法会先检查 elementData 数组的大小,如果它大于实际存储的元素数量,那么就会创建一个新的数组,只包含实际存储的元素,并将这个新数组序列化。
在反序列化时,readObject 方法会负责创建一个新的 ArrayList 实例,并恢复其元素。
总之,transient Object[] elementData; 在 ArrayList 中的作用是作为存储元素的数组,
而 transient 关键字则用于控制这个数组的序列化行为,确保序列化后的数据不包含无用信息。
*/
复制代码
当创建 ArrayList 对象是,若使用的是无参构造器,则初始的 elementData 容量为 0, 第一次添加,则扩容 elementData 为 10,若再次扩容,则扩容 elementData 为 1.5 倍(newCapacity = oldCapacity + (oldCapacity >> 1))。
若使用指定大小的构造器,则初始 elementData 容量为指定大小,若再次扩容,则直接扩容 elementData 为 1.5 倍。
ArrayList 的扩容过程
注:这些流程图使用 debug 来完成。
[code] // 扩容流程代码 ArrayList arrayList = new ArrayList(); // ArrayList arrayList = new ArrayList(8); for (int i = 1 ; i
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4