动态数组底层是如何实现的

打印 上一主题 下一主题

主题 928|帖子 928|积分 2784

动态数组底层是如何实现的
  1. 引言:
  2. 提到数组,大部分脑海里一下子想到了一堆东西
  3. int long short byte float double boolean char String
  4. 没错,他们也可以定义成数组
  5. 但是,上面都是静态的
  6. 不过,咱们今天学习的可是动态的(ArrayList 数组)
  7. 好接下来,我们一起来下面的内容
复制代码
2.1 动态数组的位置

目标:
简单认识下继承关系
ArrayList继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口

从继承关系看功能
AbstractList类
AbstractList,实现了List。List接口我们都知道,提供了相关的添加、删除、修改、遍历等功能
RandmoAccess接口
ArrayList 实现了RandmoAccess接口,即提供了随机访问功能; 即list.get(i)
Cloneable接口
ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆
Serializable接口
ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输
2.2.动态数组与数据结构

目标:
图解+面试题快速认识ArrayList
1) 概念介绍
ArrayList 是一个数组队列,相当于动态(扩容)数组。
我们直接来看对象头,对其有个简单认识和猜想:(com.alist.InitialList)
  1. package com.alist;
  2. import org.openjdk.jol.info.ClassLayout;
  3. import java.util.ArrayList;
  4. public class ArrayListHeader {
  5.     public static void main(String[] args) {
  6.         int[] i = new int[8];
  7.         ArrayList<Integer> list = new ArrayList(8);
  8.         //将8个int类型依次放入数组和arrayList,注意,一个int占4个字节
  9.         for (int j = 0; j < 8; j++) {
  10.             i[j] = j;
  11.             list.add(j);
  12.         }
  13.         System.out.println(ClassLayout.parseInstance(i).toPrintable());
  14.         System.out.println("=============");
  15.         System.out.println(ClassLayout.parseInstance(list).toPrintable());
  16. //        System.out.println(ClassLayout.parseClass(ArrayList.class));
  17.     }
  18. }
复制代码
2)  执行结果分析:

从对象头,我们大致可以看出ArrayList的数据结构:

  • ArrayList底层用一个数组存储数据:elementData
  • 额外附加了几组信息:modeCount(发生修改操作的次数)、size(当前数组的长度)
等会……

  • 为什么长度不是数组里的32,而是4个字节?ArrayList的长度到底应该是多少???
  • 这个数组后面多出来俩null又是怎么回事???
(下面构造函数部分会得到详细答案)
3) 结论 & 面试题
ArrayList外围暴露出来的只是一些操作的表象,底层数据的存储和操作都是基于数组的基础上
这就意味着,它的特性和数组一样:查询快!删除插入慢。
ArrayList访问为什么那么快?
1、ArrayList底层是数组实现的
2、数组是一块连续的内存空间
3、获取数据可以直接拿地址偏移量(get(i))

因此:查询(确切的说是访问,而不是查找)的时间复杂度是O(1)
为什么删除和增加那么慢?
增删会带来元素的移动,增加数据会向后移动,删除数据会向前移动,所以影响效率

因此:插入、删除的时间复杂度是O(N)
2.3 动态数组源码深入剖析

接下来,我们从底层源码层面看ArrayList的一系列操作
先准备测试代码,下面debug用(com.alist.AList
  1. public class AList {
  2.     public static void main(String[] args) {
  3.         ArrayList<String> arrayList = new ArrayList<String>(2);
  4.         //断点跟踪add
  5.         arrayList.add("100");
  6.         arrayList.add("200");
  7.         arrayList.add("300");
  8.         arrayList.add("400");
  9.         //断点跟踪get
  10. //        for (int i = 0; i <arrayList.size() ; i++) {
  11. //            arrayList.get(i);//Random
  12. //
  13. //        }
  14. //        //断点跟踪remove
  15. //        arrayList.remove(1);
  16. //        //arrayList.remove("100");//和上面逻辑一样remove
  17. //        System.out.println(arrayList);
  18. //         //断点跟踪set
  19. //        arrayList.set(1,"2000000");
  20. //        System.out.println(arrayList);
  21. //        //断点跟踪clear
  22. //        arrayList.clear();
  23. //        System.out.println(arrayList);
  24.     }
复制代码
3)带Collection对象的构造函数
[code]    public ArrayList(Collection

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美食家大橙子

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表