文章目录
- Java-ArrayList(动态数组)底层源码实现过程
- 1. 首先定义一个List接口:
- (1)在表尾添加元素:void add(E element):
- (2)在指定位置上添加元素:void add(int index, E element)
- 对数组的扩容、缩容方法进行实现:void resize(int newLen):
- (3)删除指定元素:void remove(E element):
- (4)移除指定元素并返回:E remove(int index)
- (5)E get(int index):获取指定角标的值
- (6)E set(int index, E element):修改指定角标的值并返回
- (7)int size():获取线性表中有效元素个数
- (8)int indexOf(E element):获取元素第一次出现的位置
- (9)boolean contains(E element);【是否包含某个元素】
- (10)boolean isEmpty();【判空】
- (11)void clear();【清空线性表】
- (12)void sort(Comparator c);【按照比较器的内容进行排序】
- (13)List subList(int fromIndex, int toIndex);【获取子线性表=》“左闭右开”】
Java-ArrayList(动态数组)底层源码实现过程
1. 首先定义一个List接口:
对于一个动态数组来说,我们需要定义如下功能(由于我们不确定将来未来数据的类型,所以我们在这里采用泛型,并且让):
*(1)void add(E element); 【在表尾添加元素】
*(2)void add(int index, E element);【在指定索引添加元素】
*(3)void remove(E element);【删除指定元素】
*(4)E remove(int index);【删除指定角标的值并返回】
*(5)E get(int index);【获取指定角标的值】
*(6)E set(int index, E element);【修改指定角标的值并返回】
*(7)int size();【获取线性表中有效元素个数】
*(8)int indexOf(E element);【获取元素第一次出现的位置】
*(9)boolean contains(E element);【是否包含某个元素】
*(10)boolean isEmpty();【判空】
*(11)void clear();【清空线性表】
*(12)void sort(Comparator<E> c);【按照比较器的内容进行排序】
*(13)List<E> subList(int fromIndex, int toIndex);【获取子线性表=》“左闭右开”】
具体实现:
首先我们先让我们自己创建的ArrayList实现我们自己定义的List接口,接着定义其成员变量:1.data数组 2.size(表示有效元素的个数、下一个元素插入的位置)
(1)在表尾添加元素:void add(E element):
@Override
public void add(E element) {
add(size, element);//直接复用add(size,element)方法
}
(2)在指定位置上添加元素:void add(int index, E element)
public void add(int index, E element){
//在指定位置上添加元素,首先判断角标是否合法
if(index < 0 || index > size){
//角标不合法,抛出异常
throw new IllegalArgumentException("add index out of range");
}
//角标合法,判断线性表是否已满
if(size == data.length){
//size表示有效元素个数,此时个数等于数组长度,表明已满
resize(2 * data.length);//数组已满,调用扩容,长度为原数组的两倍
//此处的resize方法并非是接口的,是我们ArrayList内部的
}
//扩容之后,将插入点之后的元素,向后移动[从后向前]
for(int i = size - 1; i >= index; i-- ){
data[i-1] = data[i];
}
//插入新元素
data[index] = element;
size++;
}
对数组的扩容、缩容方法进行实现:void resize(int newLen):
private void resize(int newLen){
//扩容、缩容方式不应该向外界提供,声明为私有
E[] data = (E)(new Object[newLen]);
//定义一个长度为newLen的新数组
for(int i = 0; i < size; i++){
newData[i] = data[i];//复制元素
}
data = newData;//将新数组地址赋值给data
}
(3)删除指定元素:void remove(E element):
public void remove(E element){
int index = indexOf(element);
if(index != -1){
remove(index);
}
}
(4)移除指定元素并返回:E remove(int index)
public E remove(int index){
if(index < 0 || index >= size){
throw new IllegalArgumentException("remove index out of range ");
//保存要删除的值,以便返回
E ret = data[index];
//移动元素
for(int i = index + 1; i < size; i++){
data[i-1] = data[i];
}
}
size--;
}
//缩容时机
//有效元素是容量的1/4并且当前容量必须大于默认容量
if(size == data.length / 4 && data.length > DEFAULT_CAPACITY){
resize(data.length / 2);
}
return ret;
(5)E get(int index):获取指定角标的值
public E get(int index){
if(index < 0 || index >= size){
throw new IllegalArguementException("get index out of range");
}
return data[index];
}
(6)E set(int index, E element):修改指定角标的值并返回
public E set(int index, E element){
if(index < 0 || index >= size){
throw new IllegalArgumentException("set index out of range");
}
E ret = data[index];//此处声明为E,因为不确定未来ArrayList传入的数据类型
data[index] = element;
return ret;
}
(7)int size():获取线性表中有效元素个数
public int size(){
return size;
}
(8)int indexOf(E element):获取元素第一次出现的位置
public int indexOf(E element){
for(int i = 0; i < size; i++){
if(data.equals(element)){
return i;//使用equals,可能传入的是引用数据类型
}
}
return -1;//表明没有找到
}
(9)boolean contains(E element);【是否包含某个元素】
public boolean contains(E element){
return indexOf(element) != -1;
}
(10)boolean isEmpty();【判空】
public boolean isEmpty(){
return size == 0;
}
(11)void clear();【清空线性表】
public void clear(){
data = (E[])(new Object[DEAULT_CAPACITY]);//直接让data指向新的数组
size = 0;
}
(12)void sort(Comparator c);【按照比较器的内容进行排序】
public void sort(Comparator<E> c){
if(c == null){
throw new IllegalArgumentException("comparator can not be null");
}
//排序我们采用优化后的插入排序
for(int i = 1; i < size; i++){
}
}
(13)List subList(int fromIndex, int toIndex);【获取子线性表=》“左闭右开”】
public List<E> subList(fromIndex, int toIndex){
if(fromIndex < 0 || toIndex >= size || fromIndex > toIndex){
throw new IllegalArgumentException("must 0 <= fromIndex <= toIndex <= size - 1");
}
ArrayList<E> list = new ArrayList<>();
for(int i = fromIndex; i <= toIndex; i++){
list.add(data[i]);
}
return list;
}
接下来是全部代码:
1.实现List接口:
package p1.接口;
import java.util.Comparator;
//线性表接口定义
public interface List<E> extends Iterable<E> {
//默认在表尾添加一个元素
public void add(E element);
//在指定角标处添加元素
public void add(int index, E element);
//删除指定元素
public void remove(E element);
//删除指定角标处的元素 并返回原先的值
public E remove(int index);
//获取指定角标处的元素
public E get(int index);
//修改指定角标index处的值为element,并返回原先的值
public E set(int index, E element);
//获取线性表中的元素个数
public int size();
//查看元素第一次出现的角标位置(从左到右)
public int indexOf(E element);
//判断是否包含元素
public boolean contains(E element);
//判断线性表是否为空
public boolean isEmpty();
//清空线性表
public void clear();
//按照比较器的内容进行排序
public void sort(Comparator<E> c);
//获取子线性表 原线性表中[formIndex, toIndex)这个部分
public List<E> subList(int fromIndex, int toIndex);
}
2.实现ArrayList:
package p2.线性结构;
import p1.接口.List;
import java.util.Comparator;
import java.util.Iterator;
//自定义的线性表的顺序存储方式
public class ArrayList<E> implements List<E> {
//定义数组的容器 data.length 指的就是当前数组的容量
private E[] data;
//元素的个数 size == 0 线性表为空表 size == data.length 线性表满了
//size 新元素默认尾部添加时要去的角标
private int size;
//默认容量
private static int DEAULT_CAPACITY = 10;
//默认构造函数:创建一个默认容量为10的线性表
public ArrayList(){
data = (E[]) new Object[DEAULT_CAPACITY];
size = 0;
}
//指定默认容量的构造函数:创建一个指定容量的线性表
public ArrayList(int capacity){
if(capacity <= 0){
throw new IllegalArgumentException("capacity must > 0");
}
DEAULT_CAPACITY = capacity;
data = (E[]) new Object[DEAULT_CAPACITY];
size = 0;
}
//指定数组的构造函数:传入一个数组 将该数组封装成为一个线性表
public ArrayList(E[] arr){
if(arr == null || arr.length == 0){
throw new IllegalArgumentException("arr can not be null");
}
data = (E[]) new Object[DEAULT_CAPACITY];
for(int i = 0; i < arr.length; i++){
add(arr[i]);
}
}
@Override
public void add(E element) {
add(size, element);
}
@Override
public void add(int index, E element) {
if(index < 0 || index > size){
throw new IllegalArgumentException("add index out of range");
}
//判断线性表是否是满状态
if(size == data.length){
resize(2 * data.length);
}
//向后移动元素
for(int i = size - 1; i >= index; i--){
data[i + 1] = data[i];
}
//将新元素插入到指定位置
data[index] = element;
size++;
}
//扩容/缩容操作 不应该向外界提供
private void resize(int newLen) {
E[] newData = (E[]) new Object[newLen];
for(int i = 0; i < size; i++) {
newData[i] = data[i];
}
data = newData;
}
@Override
public void remove(E element) {//删除指定元素 只删除一次 || 删除所有指定元素(此处只删除一次)
int index = indexOf(element);
if(index != -1){
remove(index);
}
}
@Override
public E remove(int index) {
if(index < 0 || index >= size){//可以判空
throw new IllegalArgumentException("remove index out of range");
}
//先保存要删除的值
E ret = data[index];
//移动元素
for(int i = index + 1; i < size; i++){
data[i-1] = data[i];
}
size--;
//什么时候缩容
//1.有效元素是容量的1/4
//2.当前容量不得小于等于默认容量
if(size == data.length / 4 && data.length > DEAULT_CAPACITY){
resize(data.length / 2);
}
return ret;
}
@Override
public E get(int index) {
if(index < 0 || index >= size){
throw new IllegalArgumentException("get index out of range");
}
return data[index];
}
@Override
public E set(int index, E element) {
if(index < 0 || index >= size){
throw new IllegalArgumentException("set index out of range");
}
E ret = data[index];
data[index] = element;
return ret;
}
@Override
public int size() {
return size;
}
//额外添加的函数 获取线性表中那个的容量
private int getCapacity() {
return data.length;
}
@Override
public int indexOf(E element) {
/*
== 比的是啥?
== 两边是基本数据类型的话 比的是值
基本数据类型:byte short int long float double boolean char
== 两边是引用数据类型的话 比的是地址
数组 字符串 其他的类对象
*/
for(int i = 0; i < size; i++){
if(data[i].equals(element)){
return i;//return结束函数
}
}
return -1;
}
@Override
public boolean contains(E element) {
return indexOf(element) != -1;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void clear() {
data = (E[]) new Object[DEAULT_CAPACITY];
size = 0;
}
@Override
public void sort(Comparator<E> c) {
if(c == null){
throw new IllegalArgumentException("comparator can not be null");
}
//插入排序(优化),从第二个元素开始
for(int i = 1; i < size; i++){
E e = data[i];
int j = 0;
for(j = i; j > 0 && c.compare(data[j-1],e) > 0; j--){
data[j] = data[j-1];
}
data[j] = e;
}
}
@Override
public List subList(int fromIndex, int toIndex) {
if(fromIndex < 0 || toIndex >= size || fromIndex > toIndex){
throw new IllegalArgumentException("must 0 <= fromIndex <= toIndex <= size - 1");
}
ArrayList<E> list = new ArrayList<>();
for(int i = fromIndex; i <= toIndex; i++){
list.add(data[i]);
}
return list;
}
@Override
public boolean equals(Object o) {
//1.判空
if(o == null){
return false;
}
//2.判自己
if(this == o){
return true;
}
//3.判类型
if(o instanceof ArrayList){
//4.按照自己的逻辑比较
ArrayList<E> other = (ArrayList<E>) o;
//5.先比较有效元素的个数
if(this.size != other.size){
return false;
}
//6.有效元素个数相等的情况下 逐个比较元素
for(int i = 0; i < size; i++){
if(!data[i].equals(other.data[i])){
return false;
}
}
return true;
}
return false;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
if (isEmpty()) {
sb.append(']');
} else {
for (int i = 0; i < size; i++) {
sb.append(data[i]);
if (i == size - 1) {
sb.append(']');
} else {
sb.append(',');
sb.append(' ');
}
}
}
return sb.toString();
}
//获取当前这个数据结构/容器的迭代器
//通过迭代器对象 更方便的挨个去除每一个元素
//同时 实现了Iterable 可以让当前的数据结构/容器 被foreach循环遍历
@Override
public Iterator iterator() {
return new ArrayListIterator();
}
//创建一个属于ArrayList的迭代器
class ArrayListIterator implements Iterator<E> {//内部类
private int cur = 0;
@Override
public boolean hasNext() { //判断是否有下一个元素
return cur < size;
}
@Override
public E next() { //如果有下一个元素,则把当前元素返回 并移至到下一个元素
return data[cur++];
}
}
}
测试结果:
package p0.测试;
import p2.线性结构.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Random;
public class TestArrayList {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
System.out.println(list);
Random random = new Random();
for (int i = 0; i < 10; i++) {
list.add(random.nextInt(100));
}
System.out.println(list);
for (int i = 0; i < 10; i++) {
list.add(0, i);
}
System.out.println(list);
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(list);
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
}
}
[]
[4, 18, 17, 83, 54, 90, 28, 8, 94, 24]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 4, 18, 17, 83, 54, 90, 28, 8, 94, 24]
[94, 90, 83, 54, 28, 24, 18, 17, 9, 8, 8, 7, 6, 5, 4, 4, 3, 2, 1, 0]
94 90 83 54 28 24 18 17 9 8 8 7 6 5 4 4 3 2 1 0