1.结构特性

Java ArrayList类使用动态数组来存储元素。它就像一个数组,但是没有大小限制。 可以随时添加或删除元素。有以下特性:

  • 底层使用数组来存储元素
  • 没有固定的容量限制,底层数组会自动扩容
  • 允许包含null值
  • 允许包含重复的值
  • 保存了元素的添加顺序
  • 不是线程安全的

2.构造函数

// 1.构建一个空的数组列表
ArrayList() // 2.构造了一个包含指定元素集合的数组列表
ArrayList(Collection<? extends E> c) // 3.构建一个数组列表,指定初始化容量
ArrayList(int initialCapacity)

3.成员变量

// ArryList包含的元素数量
private int size; // ArrayList底层装载元素的数组
transient Object[] elementData;

4.常用的成员方法

// 1.增加元素到数组列表尾部
boolean add(E e) // 2.增加元素到指定位置
void add(int index, E element) // 3.获取指定位置的元素
E get(int index) // 4.设置指定位置的元素
E set(int index, E element) // 5.检查包含指定元素
E remove(int index) // 6.返回指定元素在此列表中首次出现的索引
int indexOf(Object o) // 7.返回一个数组包含所有的元素
Object[] toArray() // 8.返回此列表中指定的fromIndex(包括)和toIndex(不包括)之间的视图。
List<E> subList(int fromIndex, int toIndex) // 9.移除数组列表中所有的元素
void clear() // 10.返回true表示数组列表中没有任何元素
boolean isEmpty() // 11.数组列表中包含的元素个数
int size() // 12.检查并增加ArrayList实例的容量,以确保它至少可以容纳参数指定的元素数量。
void ensureCapacity(int minCapacity)

5.底层数组扩容原理

1.添加元素的时候,首先检查并增加底层elementData的容量,以确保它至少可以容纳指定的元素数量。

public boolean add(E e) {
// 检查容量
ensureCapacityInternal(size + 1); // Increments modCount!!
......
}

2.新的容量是在原容量的基础上增加 50 %

 private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 计算新容量
int newCapacity = oldCapacity + (oldCapacity >> 1);
......
}

3.将elementData 中元素拷贝到一个新数组,索引位置的元素保持不变,然后将新的数组实例赋值给 elementData。

private void grow(int minCapacity) {
......
// 拷贝新数组
elementData = Arrays.copyOf(elementData, newCapacity);
}

6.序列化原理

1.通过ArrayList的声明可以看到实现了Serializable接口,对象可以序列化。

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
......
}

2.序列化时调用 writeObject() 方法将size和element写入ObjectOutputStream。

private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
......
}

3.反序列化时调用readObject,从ObjectInputStream获取size和element,再恢复到elementData。

private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
......
}

4.成员变量 elementData 是一个缓存数组,会预留一些容量,使用了 transient 关键字修饰,不会序列化到目的地中,从而节省时间和空间。

7.集合元素排序

1.使用Collections.sort()方法传入 ArrayList 实例进行排序(字典序)

@Test
public void testArrayListSort () {
ArrayList<String> list = new ArrayList<>(10);
list.add("one");
list.add("two");
Collections.sort(list);
System.out.println(list); // output: [one, two]
}

2.使用Collections.sort()方法传入 ArrayList 实例和Commparator接口的类的对象,实现自定义排序。

@Test
public void testArrayListSort () {
ArrayList<Integer> list = new ArrayList<>(10);
list.add(20);
list.add(18);
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
System.out.println(list); // output: [18, 20]
}

3.使用成员方法 sort() 传入Commparator接口的类的对象,实现自定义排序。

@Test
public void testArrayListSort () {
ArrayList<Integer> list = new ArrayList<>(10);
list.add(20);
list.add(18);
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
System.out.println(list); // output: [18, 20]
}

8.迭代器的实现

1.ArrayList 内部类 Itr 实现了Iterator 接口用来遍历 elementData 中的元素,调用实例的成员方法 iterator() 返回迭代器。

private class Itr implements Iterator<E> {
......
}

2.Iterator支持从前向后顺次遍历elementData中元素。

3.Itr类实现迭代器 Iterator的方法:

// 判断指针cursor是否到达elementData数组右边界
public boolean hasNext() {
return cursor != size;
} public E next() {
// 返回指针cursor指向的元素
int i = cursor;
......
// cursor右移动一位
cursor = i + 1;
return (E) elementData[lastRet = i];
} public void remove() {
......
try {
// 将新近返回的元素删除
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

9.总结

以上就是对ArrayList的理解,如果有理解不正确的地方,欢迎指正,最后,补充一张脑图:

Java集合-ArrayList源码分析的更多相关文章

  1. Java入门系列之集合ArrayList源码分析(七)

    前言 上一节我们通过排队类实现了类似ArrayList基本功能,当然还有很多欠缺考虑,只是为了我们学习集合而准备来着,本节我们来看看ArrayList源码中对于常用操作方法是如何进行的,请往下看. A ...

  2. Java中ArrayList源码分析

    一.简介 ArrayList是一个数组队列,相当于动态数组.每个ArrayList实例都有自己的容量,该容量至少和所存储数据的个数一样大小,在每次添加数据时,它会使用ensureCapacity()保 ...

  3. Java基础 ArrayList源码分析 JDK1.8

    一.概述 本篇文章记录通过阅读JDK1.8 ArrayList源码,结合自身理解分析其实现原理. ArrayList容器类的使用频率十分频繁,它具有以下特性: 其本质是一个数组,因此它是有序集合 通过 ...

  4. Java集合框架源码分析(2)LinkedList

    链表(LinkedList) 数组(array)和数组列表(ArrayList)都有一个重大的缺陷: 从数组的中间位置删除一个元素要付出很大的代价,因为数组中在被删除元素之后的所有元素都要向数组的前端 ...

  5. Java集合ArrayList源码解读

    最近在回顾数据结构,想到JDK这样好的代码资源不利用有点可惜,这是第一篇,花了心思.篇幅有点长,希望想看的朋友认真看下去,提出宝贵的意见.  :) 内部原理 ArrayList 的3个字段 priva ...

  6. Java集合-ArrayList源码解析-JDK1.8

    ◆ ArrayList简介 ◆ ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAcc ...

  7. Java集合——ArrayList源码详解

    ) ArrayList 实现了RandomAccess, Cloneable, java.io.Serializable三个标记接口,表示它自身支持快速随机访问,克隆,序列化. public clas ...

  8. 【thinking in java】ArrayList源码分析

    简介 ArrayList底层是数组实现的,可以自增扩容的数组,此外它是非线程安全的,一般多用于单线程环境下(Vector是线程安全的,所以ArrayList 性能相对Vector 会好些) Array ...

  9. Java集合-LinkedList源码分析

    目录 1.数据结构-链表 2.ArrayList结构特性 3.构造方法 4.成员变量 5.常用的成员方法 6.Node节点 7.序列化原理 8.迭代器 9.总结 1.数据结构-链表 链表(Linked ...

随机推荐

  1. LuoguP7337 『MdOI R4』Fun 题解

    Content 有 \(n\) 个人去打比赛.给出第 \(i\) 个人的交通方式 \(t_i\) 和颓废值 \(q_i\)(均以 \(0/1\) 表示).如果 \(t_i=1,q_i=1\) 的人数 ...

  2. IE上的兼容性调整问题烦死啦

    IE上的兼容性调整问题烦死啦 好像还得把此代码放到第一行才起作用.

  3. google protobuf学习笔记:windows下环境配置

    欢迎转载,转载请注明原文地址:http://blog.csdn.net/majianfei1023/article/details/45371743 protobuf的使用和原理,请查看:http:/ ...

  4. 【LeetCode】1119. Remove Vowels from a String 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 判断字符是否是aeiou 日期 题目地址:https: ...

  5. Windows服务注册(需要指定config文件的情况下)

    最近,遇到一个问题:需要将telegraf在Win平台下注册为windows服务(避免误操作关闭CMD窗口): 尝试了网上的几种注册Windows服务的方法,发现无法将telegraf这种需要在CMD ...

  6. Java代码性能优化

    (1)在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 控制资源的使用,通过线程同步来控制资源的并 ...

  7. cosface: large margin cosine loss for deep face recognition

    目录 概 主要内容 Wang H, Wang Y, Zhou Z, et al. CosFace: Large Margin Cosine Loss for Deep Face Recognition ...

  8. 离线版centos8环境部署迁移监控操作笔记

    嗨咯,前两天总结记录了离线版centos8下docker的部署笔记,今天正好是2021年的最后一天,今天正好坐在本次出差回家的列车上,车上没有上面事做,索性不如把本次离线版centos8环境安装的其他 ...

  9. Java的generator工具类,数据库生成实体类和映射文件

    首先需要几个jar包: freemarker-2.3.23.jar log4j-1.2.16.jar mybatis-3.2.3.jar mybatis-generator-core-1.3.2.ja ...

  10. Python猫 2021 文章小结,翻译竟比原创多!

    最近给自己放了两周的"长假",刷视频.看小说.玩游戏,就是不写文章不更新公众号. 半途而废的事情令得 2021 年的时间流逝加快,最后留下只是遗憾和不甘. 又到了新的一年,按照惯例 ...