ArrayList的底层本质是一个能够动态操作数据的Object数组,它实现了List接口(其提供了相关的添加、删除、修改、遍历等功能)。
- 模拟建立List接口
package com.data;
/**
* 线性表接口
*/
public interface List {
//返回线性表的大小,即数据元素个数
public int size();
//返回线性表中序号为index的元素
public Object get(int index);
//如果线性表为空返回true,否则返回false
public boolean isEmpty();
//判断线性表是否包含 指定元素
public boolean contains(Object e);
//返回数据元素e在线性表中的序号
public int indexOf(Object e);
//将数据元素e插到线性表中的index位置
public void add(int index,Object e);
//将数据元素e插到线性表中的末尾
public void add(Object e);
//将数据元素e插到元素obj之前
public boolean addBefore(Object obj,Object e);
//将数据元素e插到元素obj之后
public boolean addAfter(Object obj,Object e);
//删除线性表中序号为index的元素,并返回之
public Object remove(int index);
//删除线性表中第一个与e相同的元素
public Object remove(Object e);
//用元素e替换线性表中序号为index的元素,并返回原元素
public Object replace(int index,Object e);
}
- 自定义异常类
package com.data.exception;
/**
* 自定义异常类
*/
public class ArrayIndexOutOfBoundsException extends RuntimeException{
public ArrayIndexOutOfBoundsException(){
super();
}
public ArrayIndexOutOfBoundsException(String message){
super(message);
}
}
- 新建ArrayList类并实现List接口
package com.data.genericset;
import com.data.List;
import com.data.exception.ArrayIndexOutOfBoundsException;
import java.util.Arrays;
/**
* 顺序表(底层采用的是数组,但长度可以动态的变化)
*/
public class ArrayList implements List {
private Object[] elementData;//底层是一个未定义长度的数据
private int size;//元素的个数
public ArrayList(){
//没有指定数组初始长度,设置默认长度为0
//this.elementData = new Object[]{};
this(4);
}
/**
* 构造方法初始化数组
* @param initialCapacity 数据的初始指定长度
*/
public ArrayList(int initialCapacity){
//为数据分配指定的数量空间
this.elementData = new Object[initialCapacity];
//指定顺序表的元素个数,默认是0
size = 0;
}
@Override
public int size() {
return this.size;
}
@Override
public Object get(int index) {
if(index<0||index>=size){
throw new ArrayIndexOutOfBoundsException("数组索引越界异常:"+index);
}
return this.elementData[index];
}
@Override
public boolean isEmpty() {
return this.size==0;
}
@Override
public boolean contains(Object e) {
if(this.indexOf(e)!=-1){
return true;
}
return false;
}
@Override
public int indexOf(Object e) {
if(e==null){
return -1;
}
for(int x=0;x<this.size;x++){
if(this.elementData[x].equals(e)){
return x;
}
}
return -1;
}
@Override
public void add(int index, Object e) {
//判断index的位置是否正确
if(index<0||index>this.size){
throw new ArrayIndexOutOfBoundsException("数组索引越界异常:"+index);
}
//如果数组满了,就扩容
if(this.size==this.elementData.length){
this.grow();
}
//后移index及其后面的元素元素,从最后一个元素开始
for(int x=this.size;x>index;x--){
this.elementData[x] = this.elementData[x-1];
}
//为数据赋值,线性表中的元素个数加1
this.elementData[index]=e;
this.size++;
}
@Override
public void add(Object e) {
this.add(this.size,e);
}
@Override
public boolean addBefore(Object obj, Object e) {
int index = this.indexOf(obj);
if(index==-1){//查询不到数据
return false;
}else{
this.add(index,e);
}
return true;
}
@Override
public boolean addAfter(Object obj, Object e) {
int index = this.indexOf(obj);
if(index==-1){//查询不到数据
return false;
}else{
this.add(index+1,e);
}
return true;
}
@Override
public Object remove(int index) {
Object obj = null;
if(index<0||index>=this.size){//判断是否存在数据
;
}else{
obj = this.elementData[index];
for(int x=index;x<this.size-1;x++){
this.elementData[x] = this.elementData[x+1];
}
this.size--;
}
return obj;
}
@Override
public Object remove(Object e) {
return this.remove(this.indexOf(e));
}
@Override
public Object replace(int index, Object e) {
if(index<0||index>=this.size){//判断是否存在数据
return null;
}
Object obj = this.elementData[index];
this.elementData[index] = e;
return obj;
}
private void grow(){
//复制创建新的数组,数组长度增长50%;
this.elementData = Arrays.copyOf(this.elementData,
this.elementData.length+(this.elementData.length>>1));
}
@Override
public String toString() {
if(this.size==0){
return "[]";
}
/**
String只能存放不可变的字符串,而StringBuffer和StringBuilder存放可变的字符串
String与StringBuilder是线程非安全的(速度较快),而StringBuffer是线程安全的(速度较慢)
考虑到此处为单线程操作,因此使用StringBuilder
*/
StringBuilder builder = new StringBuilder("[");
for(int x=0;x<this.size;x++){
builder.append(this.elementData[x]).append(",");
}
builder.delete(builder.length()-1,builder.length()).append("]");
return builder.toString();
}
}
- 编写测试代码
import com.data.List;
import com.data.genericset.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add(123);
list.add(456);
list.add(789);
list.add(555);
list.add(0,"haha");
System.out.println("数组长度:"+list.size());
System.out.println("是否为空:"+list.isEmpty());
System.out.println("是否包含haha:"+list.contains("haha"));
System.out.println("haha位置:"+list.indexOf("haha"));
System.out.println("输出集合:"+list);
System.out.println("在haha之前插入hello:"+list.addBefore("haha","hello"));
System.out.println("输出集合:"+list);
System.out.println("在haha之后插后world:"+list.addAfter("haha","world"));
System.out.println("输出集合:"+list);
System.out.println("删除第5个元素:"+list.remove(5));
System.out.println("输出集合:"+list);
System.out.println("删除haha:"+list.remove("haha"));
System.out.println("输出集合:"+list);
System.out.println("将最后一个元素换成haha:"+list.replace(list.size()-1,"haha"));
System.out.println("输出集合:"+list);
}
}
- 运行程序查看控制台输出,发现所有操作都能正常完成。