1. 定义一个List接口
package com.cqc.ArrayList;
/**
* 线性表接口
* 和存储结构无关
* @author Administrator
*
*/
public interface List {
//返回线性表的大小,即数据元素的个数
public int size();
//返回线性表中序号为i的数据元素
public Object get(int i);
//判断线性表是否为空,空为true,否则为false
public boolean isEmpty();
//判断线性表是否包含数据元素e
public boolean contains(Object e);
//返回数据元素e在线性表中序号
public int indexOf(Object e);
//将数据元素e插入到线性表的i号位置
public void add(int i,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);
//删除线性表中序号为i的元素,并返回之
public Object remove(int i);
//删除线性表中第一个与e相同的元素
public boolean remove(Object e);
//替换线性表中序号为i的数据元素为e,返回原数据元素
public Object replace(int i,Object e);
}
2. 创建类ArrayList实现自定义List接口
package com.cqc.ArrayList;
import java.util.Arrays;
/**
* 顺序表,底层是数组,长度可以动态变化,使用扩容机制
*/
public class ArrayList implements List {
private Object[] elementData; //根据java.util.ArrayList,底层使用数组,元素为Object类型,没有确定长度
private int size; //不是数组长度,而是元素的个数,默认为0
/**
* 有参构造
* @param initialCapacity 指定数组的初始长度
*/
public ArrayList(int initialCapacity) {
//给数组elementData分配空间
elementData = new Object[initialCapacity];
}
/**
* 无参构造方法,调用有参方法,指定数组长度
*/
public ArrayList(){
this(4); //指定默认长度为4
//不指定长度,长度为0
// elementData = new Object[]{};
}
@Override
public int size() {
//返回数组元素个数
return size;
}
@Override
public Object get(int i) {
//按索引返回数组的元素
return elementData[i];
}
@Override
public boolean isEmpty() {
//size为0,则为true
return size==0;
}
@Override
public boolean contains(Object e) {
//若果这个对象的索引在这个数组内,索引不为-1
return indexOf(e) >= 0;
}
@Override
public int indexOf(Object e) {
//分为null和非null两种处理方式
if(e == null){
//遍历查找第一个为null的index
for(int i =0;i<size;i++){
if(elementData[i] == null){
return i;
}
}
}else {
//查找第一个等于
for(int i=0;i<size;i++){
if(elementData[i] == e){
return i;
}
}
}
//若没有找到,返回-1
return -1;
}
@Override
public void add(int i, Object e) {
//添加时先判断数组是否满了,如果满了,就扩容
if(elementData.length == size){
grow();
}
//后移索引i和后边的元素,从最后一个开始
for(int j=size;j>i;j--){ //j表示的索引是现有最大索引+1
elementData[j] = elementData[j-1];
}
//将要添加的元素加进去
elementData[i] = e;
size++;
}
/**
* 添加元素,并完成扩容操作
* @param e
*/
@Override
public void add(Object e) {
// //添加时先判断数组是否满了,如果满了,就扩容
// if(elementData.length == size){
// grow();
// }
// //给数组最后一个元素后边添加新元素,数组元素个数+1
// elementData[size++] = e;
this.add(size,e);
}
//扩容,将数组长度扩容到原来的3/2
private void grow(){
// //新创建一个新的数组,长度为旧数组的2倍
// Object[] newArray = new Object[elementData.length*2];
// //将旧数组的数据copy到新数组
// for(int i =0;i<size;i++){ //有size个数据
// newArray[i] = elementData[i];
// }
// //让elementData指向新数组
// elementData = newArray;
//使用Arrays的工具类实现,指定扩容的数组,新长度,和返回的指向
elementData = Arrays.copyOf(elementData, elementData.length+elementData.length/2);
}
@Override
public boolean addBefore(Object obj, Object e) {
//获取obj的索引
int index = this.indexOf(obj);
//若数组没有此元素,添加失败
if(index == -1){
return false;
}
//进行添加操作
this.add(index,e);
return true;
}
@Override
public boolean addAfter(Object obj, Object e) {
//获取obj的索引
int index = this.indexOf(obj);
//若数组没有此元素,添加失败
if(index == -1){
return false;
}
//进行添加操作
this.add(index+1,e);
return true;
}
@Override
public Object remove(int i) {
Object o = elementData[i];
//将索引i后边的元素前移即可,最后一个元素的索引为size-1
for(int j=i;j<size-1;j++){
//若j+1为最后一个元素,应为size-1,j为size-2
elementData[j] = elementData[j+1];
}
elementData[size-1] = null;
//返回被移除的那个对象
return o;
}
@Override
public boolean remove(Object e) {
//判断数组是否包含此元素
if(contains(e)){
//删除此元素
remove(indexOf(e));
return true;
}
return false;
}
/**
* 替换元素,返回被替换的元素
* @param i
* @param e
* @return
*/
@Override
public Object replace(int i, Object e) {
Object o = elementData[i];
elementData[i]= e;
return o;
}
/**
* 打印集合中的数字,格式[123,3213,2323]
* @return
*/
@Override
public String toString() {
if(size == 0){
return "[]";
}
StringBuilder stringBuilder = new StringBuilder("["); //字符串开始符号为[
for(int i = 0 ;i<size;i++){
if(i !=size-1){
stringBuilder.append(elementData[i]+",");
}else {
stringBuilder.append(elementData[i]);
}
}
stringBuilder.append("]"); //字符串结尾符号
return stringBuilder.toString();
}
}
3. 重要的方法分析
3.1 两个重要的变量
Object[] elementData是ArrayList底层的一个数组,用来存放任意类型的元素.
size为数据中元素的个数.,根据其大小,可以判断数值是否为空,数组的元素个数.
3.2 构造方法
① 有参构造方法,给数组分配内存空间,初始值为参数的大小
② 无参构造方法:调用有参,默认分配大小为4,也可以指定为空
3.3 给底层数组扩容的方法grow()
使用Arrays工具类快捷扩容,java.util.ArrayList的扩容大小为原数组长度的3/2.
扩容步骤:new出新数组,把旧数组值拷贝到新数组,让旧数组的指针指向新数组
3.4 增加元素
首先判断数组是不是满了,满了就扩容,添加完元素,改变size大小
给指定位置增加元素: