经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
2-ArrayList底层结构和源码分析
来源:cnblogs  作者:Yao_Happy  时间:2024/7/12 9:28:43  对本文有异议

2-ArrayList底层结构和源码分析

介绍汇总:

  1. ArrayList的注意事项
  2. ArrayList的运行重要步骤
  3. 补充

1-ArrayList的注意事项

  1. ArrayList 允许添加所有的元素,包括 null ,而且还可以多个 null
  2. ArrayList 是由数组来实现数据存储的。
  3. ArrayList 基本等同于 Vector ,除了 ArrayList 是线程不安全执行效率高)看源码。在多线程情况下,不建议使用 ArrayList。
  1. // 此为 ArrayList 的 插入数据的方法
  2. // 该方法并没有关键字 synchronized 修饰,可以表明 ArrayList 是线程不安全的
  3. // synchronized 大概是加锁的意思
  4. public boolean add(E e) {
  5. ensureCapacityInternal(size + 1); // Increments modCount!!
  6. elementData[size++] = e;
  7. return true;
  8. }

2-ArrayList的运行重要步骤

  1. ArrayList 中维护了一个 Object 类型的数组 elementData 。(debug 看源码
  1. transient Object[] elementData;
  2. // 先来解释 transient 关键字
  3. /*
  4. 在Java中,transient关键字是一个变量修饰符,用来表示一个字段不应该被序列化。
  5. 当一个对象被序列化时(比如,通过ObjectOutputStream),对象的所有变量都会被写入到序列化文件中,
  6. 除了那些用transient修饰的变量。这样,当对象被反序列化时(比如,通过ObjectInputStream),
  7. transient变量将不会被恢复,它们的值将会是类型的默认值(比如,int的默认值是0,
  8. 对象的默认值是null)。
  9. */
  10. /*
  11. transient关键字主要用于以下情况:
  12. 敏感信息:如果对象的某个字段包含敏感信息,如密码或个人身份识别信息,那么应该使用transient修饰该字段,以防止这些信息被序列化到文件中。
  13. 无法序列化的对象:如果对象的某个字段引用了另一个无法序列化的对象,那么这个字段也应该用transient修饰,否则序列化过程将抛出NotSerializableException异常。
  14. 派生字段:如果对象的某个字段的值可以从其他字段派生出来,那么该字段可以用transient修饰,以节省序列化和反序列化的时间和空间。
  15. */
  16. // 解释一下 elementData 的作用
  17. /*
  18. 在 Java 的 ArrayList 类中,transient Object[] elementData; 是一个非常重要的成员变量,它用于存储 ArrayList 中的元素。
  19. ArrayList 是一个动态数组,能够根据需要自动扩容以存储更多的元素,而 elementData 就是用来实际存储这些元素的数组。
  20. transient 关键字在这里的作用是阻止 elementData 数组被自动序列化。
  21. 由于 ArrayList 实现了 Serializable 接口,它支持序列化操作,
  22. 但是 elementData 数组中的元素可能包含不应该被序列化的数据,
  23. 或者数组本身的大小(容量)可能远大于实际存储的元素数量,导致序列化后的数据包含大量无用信息。
  24. 因此,ArrayList 提供了两个私有方法 writeObject(java.io.ObjectOutputStream s) 和 readObject(java.io.ObjectInputStream s) 来控制序列化和反序列化的过程。
  25. 在序列化时,writeObject 方法会先检查 elementData 数组的大小,如果它大于实际存储的元素数量,那么就会创建一个新的数组,只包含实际存储的元素,并将这个新数组序列化。
  26. 在反序列化时,readObject 方法会负责创建一个新的 ArrayList 实例,并恢复其元素。
  27. 总之,transient Object[] elementData; 在 ArrayList 中的作用是作为存储元素的数组,
  28. 而 transient 关键字则用于控制这个数组的序列化行为,确保序列化后的数据不包含无用信息。
  29. */
  1. 当创建 ArrayList 对象是,若使用的是无参构造器,则初始的 elementData 容量为 0, 第一次添加,则扩容 elementData 为 10,若再次扩容,则扩容 elementData 为 1.5 倍(newCapacity = oldCapacity + (oldCapacity >> 1))。

  2. 若使用指定大小的构造器,则初始 elementData 容量为指定大小,若再次扩容,则直接扩容 elementData 为 1.5 倍。

  3. ArrayList 的扩容过程

注:这些流程图使用 debug 来完成。

  1. // 扩容流程代码
  2. ArrayList arrayList = new ArrayList();
  3. // ArrayList arrayList = new ArrayList(8);
  4. for (int i = 1 ; i <= 10 ; i ++) {
  5. arrayList.add(i) ;
  6. }
  7. for (int i = 11 ; i <= 15 ; i ++) {
  8. arrayList.add(i) ;
  9. }
  10. arrayList.add(100) ;
  11. arrayList.add(200) ;
  12. arrayList.add(null) ;
  13. for (Object object : arrayList) {
  14. System.out.println(object);
  15. }
  1. 注意

? ArrayList 的无参构造器与指定大小的有参构造器,区别主要是刚开始初始化内存数组的不一样.

  1. // 无参构造器
  2. public ArrayList() {
  3. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  4. }
  5. // 指定大小的有参构造器
  6. public ArrayList(int initialCapacity) {
  7. if (initialCapacity > 0) {
  8. this.elementData = new Object[initialCapacity];
  9. } else if (initialCapacity == 0) {
  10. this.elementData = EMPTY_ELEMENTDATA;
  11. } else {
  12. throw new IllegalArgumentException("Illegal Capacity: "+
  13. initialCapacity);
  14. }
  15. }

3-补充

  1. // 指定数组列表的大小为 0 的话,数组列表内部
  2. // 会将 elementData = EMPTY_ELEMENTDATA
  3. // 区别于 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
  4. // 从源码中看,虽然都是空数组,但是他们扩容时不同
  5. // DEFAULTCAPACITY_EMPTY_ELEMENTDATA 第一次扩会扩成容量为 10 ,之后就是其 1.5 倍扩
  6. // EMPTY_ELEMENTDATA 首次及第二次扩都以 minCapcity 来扩,之后可能都是其 1.5 倍扩
  7. ArrayList arrayList = new ArrayList(0);
  8. for (int i = 1 ; i <= 10 ; i ++) {
  9. arrayList.add(i) ;
  10. }
  11. for (int i = 11 ; i <= 15 ; i ++) {
  12. arrayList.add(i) ;
  13. }
  14. arrayList.add(100) ;
  15. arrayList.add(200) ;
  16. arrayList.add(null) ;
  17. for (Object object : arrayList) {
  18. System.out.println(object);
  19. }

原文链接:https://www.cnblogs.com/Yao-happy/p/18296947

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号