ArrayList是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般是用数组完成的。ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表 。
public class MyArrayList {
private int[] elem;
//顺序表实际的长度
private int usedSize;
private static final int DEFAULT_SIZE = 10;
//默认初始化大小为10
public MyArrayList() {
this.elem = new int[DEFAULT_SIZE];
}
// 自己指定顺序表的底层容量设置为initCapacity
MyArrayList(int initCapacity) {
this.elem = new int[initCapacity];
}
}
以下是ArrayList的常见方法
// 新增元素,默认在数组最后新增
public void add(int data)
// 在 pos 位置新增元素
public void add(int pos, int data)
// 判定是否包含某个元素
public boolean contains(int toFind)
// 查找某个元素对应的位置
public int indexOf(int toFind)
// 获取 pos 位置的元素
public int get(int pos)
// 给 pos 位置的元素设为 value
public void set(int pos, int value)
//删除第一次出现的关键字key
public void remove(int toRemove)
// 获取顺序表长度
public int size()
// 清空顺序表
public void clear()
在实现这些方法之前我们先来写一个判断数组是否装满的方法来判断顺序表是否装满
//判断数组是否装满
public boolean isFull() {
return this.elem.length == usedSize;
}
实现add方法( 默认在数组最后新增元素)
public void add(int data) {
//判断顺序表是否装满 满了我们就需要扩容
if (isFull()) {
//扩容为原来的两倍 ArrayList底层是1.5倍扩容
this.elem = Arrays.copyOf(this.elem, this.elem.length * 2);
}
//把元素存到数组里
this.elem[usedSize] = data;
//数组长度+1
this.usedSize++;
}
实现add方法(在指定位置新增元素)
因为指定的位置有可能不合法,不在数组长度范围内我们可以写一个方法来判断位置是否合法,不合法我们可以自定义一个异常
public class PosOutOfBoundsException extends RuntimeException {
public PosOutOfBoundsException() {
}
public PosOutOfBoundsException(String message) {
super(message);
}
}
public void check(int pos) {
//如果pos小于0或大于数组的实际长度我们就认为它不合法
if (pos < 0 || pos > this.usedSize) {
throw new PosOutOfBoundsException("pos不合法 " + pos);
}
}
public void add(int pos, int data) {
//检查pos是否合法
check(pos);
//判断数组元素是否已满
if (isFull()) {
//扩容
this.elem = Arrays.copyOf(this.elem, this.elem.length * 2);
}
//把元素向后移动
for (int i = this.usedSize - 1; i >= pos; i--) {
elem[i + 1] = elem[i];
}
//插入元素
elem[pos] = data;
this.usedSize++;
}
实现contains方法(判定是否包含某个元素)
public boolean contains(int toFind) {
for (int i = 0; i < this.usedSize; i++) {
if (this.elem[i] == toFind) {
return true;
}
}
return false;
}
实现indexOf方法(查找某个元素对应的位置)
public int indexOf(int toFind) {
for (int i = 0; i < this.usedSize; i++) {
if (this.elem[i] == toFind) {
return i;
}
}
return -1;
}
实现get方法(获取某个位置的元素)
获取元素之前我们应该先判断一下要获取的位置是否合法
public int get(int pos) {
check(pos);
return this.elem[pos];
}
实现set方法(把某个位置的元素设置成value)
和get方法一样我们应该先判断位置是否合法
public void set(int pos, int value) {
check(pos);
this.elem[pos] = value;
}
实现remove方法(删除第一次出现的元素)
在删除元素之前我们应该先确认要删除的元素是否在数组中,如果在就删除
public void remove(int toRemove) {
//判断要删除的toRemove是否在数组中 在返回toRemove的下标 否则返回-1
int index = indexOf(toRemove);
if (index==-1) {
System.out.println("没有找到 "+toRemove);
}
for (int i = index; i < this.usedSize-1; i++) {
this.elem[i] = this.elem[i+1];
}
this.usedSize--;
}
实现size方法(获取顺序表的长度)
要获取长度很简单,我们只需要知道usedSize的大小就行了,因为usedSize就是顺序表的实际长度
public int size() {
return this.usedSize;
}
实现clear方法(清空顺序表)
同样的清空顺序表我们只需要把usedSize的大小改成0就可以了
public void clear() {
//如果是引用数据类型
// for (int i = 0; i < this.usedSize; i++) {
// this.elem[i] = null;
// }
this.usedSize = 0;
}