Java数据结构——ArrayList
目录
一、线性表
二、顺序表(模拟实现)
2.1需要模拟实现的接口功能
2.2 具体功能实现
2.2.1 初始化
2.2.2 扩容
2.2.3 add(int data) 尾插
2.2.4 add(int pos,int data) 插入到指定位置
2.2.5 contains(int toFind)
2.2.6 查询元素的位置
2.2.7 查询位置的元素
2.2.8 设置指定位置的元素
2.2.9 删除元素
2.2.10 打印
2.2.11 判满 和 判空
三、ArrayList简介
四、ArrayList使用
4.1 ArrayList的构造
4.1.1 无参构造
4.1.2 指定容量构造
4.1.3 利用其他collection构造
4.2 ArrayList的常见操作
4.3 ArrayList的遍历
4.3.1 for + 下标 循环
4.3.2 for each 循环
4.3.3 迭代器循环
一、线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
二、顺序表(模拟实现)
2.1需要模拟实现的接口功能
public interface IList {// 新增元素,默认在数组最后新增void add(int data);// 在 pos 位置新增元素void add(int pos, int data);// 判定是否包含某个元素boolean contains(int toFind);// 查找某个元素对应的位置int indexOf(int toFind);// 获取 pos 位置的元素int get(int pos);// 给 pos 位置的元素设为 valuevoid set(int pos, int value);//删除第一次出现的关键字keyvoid remove(int toRemove);// 获取顺序表长度int size();// 清空顺序表void clear();// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出void display();//判断满boolean isFull();//判断空boolean isEmpty();
}
2.2 具体功能实现
2.2.1 初始化
public class MyArrayList implements IList{public int[] elem;public int usedSize;//有效数据个数public MyArrayList(){this.elem=new int[10];}
}
顺序表的底层是用数组实现的,在构造方法中先初始化10个数组容量
2.2.2 扩容
private void resize(){elem= Arrays.copyOf(elem,2*elem.length);}
如果数组空间不够,我们将数组大小扩大两倍
2.2.3 add(int data) 尾插
@Overridepublic void add(int data) {//尾插if(isFull()){//扩容resize();}elem[usedSize]=data;usedSize++;}
尾插就是把数据插入到数组有效个数的下一个位置,插入之前我们需要判断是否空间满了,如果满了则扩容,尾插后有效数据个数也要+1
2.2.4 add(int pos,int data) 插入到指定位置
@Overridepublic void add(int pos, int data) {//把数据存放到指定位置//顺序表插入数据的时候一定要有一个唯一的前驱,不可以跳着插入if(pos<0||pos>usedSize){throw new PosOutException("pos位置不合法");}if(isFull()){resize();}for(int i=usedSize-1;i>=pos;i--){elem[i+1]=elem[i];}elem[pos]=data;usedSize++;}
插入到pos位置,首先我们需要保证pos位置的合法性,如果pos<0或者pos>usedSize则pos位置违法,因为插入的位置必须有前驱,不可以留有空位。如下图pos=5>usedSize,则留有空位违法
如果我们要在中间插入数据,我们需要移动pos位置之后的数据
我们需要从后往前移动数据,这样才能保证不被覆盖
如果采用下面的移动方法,从前往后移动,数据就会被覆盖
2.2.5 contains(int toFind)
查询顺序表是否包含查询的元素
@Overridepublic boolean contains(int toFind) {if(isEmpty()) return false;for(int i=0;i<usedSize;i++){if(elem[i]==toFind){return true;}}return false;}
2.2.6 查询元素的位置
@Overridepublic int indexOf(int toFind) {if(isEmpty()){return -1;}for (int i = 0; i < usedSize; i++) {if(elem[i]==toFind){return i;}}return -1;}
2.2.7 查询位置的元素
@Overridepublic int get(int pos) {if(pos<0||pos>=usedSize){throw new PosOutException("pos位置不合法");}return elem[pos];}
2.2.8 设置指定位置的元素
@Overridepublic void set(int pos, int value) {if(pos<0||pos>=usedSize){throw new PosOutException("pos位置不合法");}elem[pos]=value;}
2.2.9 删除元素
@Overridepublic void remove(int toRemove) {int index=indexOf(toRemove);if(index==-1) return;for(int i=0;i<usedSize-1;i++){elem[i]=elem[i+1];}usedSize--;}
删除元素跟添加元素相反,我们把元素从前到后往前一个位置移动
2.2.10 打印
@Overridepublic void display() {for (int i = 0; i < usedSize; i++) {System.out.print(elem[i]+" ");}}
2.2.11 判满 和 判空
@Overridepublic boolean isFull() {if(elem.length==usedSize){return false;}else{return true;}}@Overridepublic boolean isEmpty(){if(usedSize==0){return true;}else{return false;}}
三、ArrayList简介
ArrayList是一个普通的类,实现了List接口,具体框架图如下
- ArrayList是以泛型方式实现的,使用时必须要先实例化
- ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
- ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
- ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
- 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList
- ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表
四、ArrayList使用
4.1 ArrayList的构造
4.1.1 无参构造
public static void main(String[] args) {//构造一个空的顺序表ArrayList<Integer> arrayList=new ArrayList<>();}
4.1.2 指定容量构造
public static void main(String[] args) {//构造一个容量为3的顺序表ArrayList<Integer> arrayList=new ArrayList<>(10);arrayList.add(1);arrayList.add(2);arrayList.add(3);System.out.println(arrayList); // [1, 2, 3]}
4.1.3 利用其他collection构造
public static void main(String[] args) {ArrayList<Integer> arrayList=new ArrayList<>();arrayList.add(1);arrayList.add(2);arrayList.add(3);System.out.println(arrayList); //[1, 2, 3]ArrayList<Integer> arrayList1=new ArrayList<>(arrayList);arrayList1.add(99);System.out.println(arrayList1); //[1, 2, 3, 99]}
4.2 ArrayList的常见操作
方法 | 解释 |
boolean add(E e) | 尾插e |
void add(int index,E element) | 将e插入到index位置 |
boolean addAll(Collection<? extends E> c) | 尾插c中的元素 |
E remove(int index) | 删除index位置元素 |
boolean remove(Object o) | 删除遇到的第一个o |
E get(int index) | 获取下标index位置元素 |
E set(int index,E element) | 将下标index位置元素设置为element |
void clear() | 清空 |
boolean contains(Object o) | 判断o是否在线性表中 |
int indexOf(Object o) | 返回第一个o所在下标 |
int lastIndexOf(Object o) | 返回最后一个o的下标 |
List<E> subList(int fromIndex,int toIndex) | 截取部分list |
4.3 ArrayList的遍历
4.3.1 for + 下标 循环
public static void main(String[] args) {ArrayList<Integer> list=new ArrayList<>();list.add(0);list.add(1);list.add(2);list.add(3);list.add(4);System.out.println(list);System.out.println("====for+下标=======");for(int i=0;i<list.size();i++){System.out.print(list.get(i)+" ");}}
4.3.2 for each 循环
public static void main(String[] args) {ArrayList<Integer> list=new ArrayList<>();list.add(0);list.add(1);list.add(2);list.add(3);list.add(4);System.out.println(list);System.out.println("=====for each循环=======");for (Integer x:list) {System.out.print(x+" ");}}
4.3.3 迭代器循环
public static void main(String[] args) {ArrayList<Integer> list=new ArrayList<>();list.add(0);list.add(1);list.add(2);list.add(3);list.add(4);System.out.println(list);System.out.println();System.out.println("======Iterator迭代器遍历======="); //0 1 2 3 4 Iterator<Integer> it=list.iterator();while(it.hasNext()){System.out.print(it.next()+" ");}System.out.println();System.out.println("=======ListIterator迭代器遍历2========"); //0 1 2 3 4 ListIterator<Integer> lit=list.listIterator();while(lit.hasNext()){System.out.print(lit.next()+" ");}System.out.println();System.out.println("=====逆序迭代器遍历3======="); //4 3 2 1 0 ListIterator<Integer> litPrev=list.listIterator(list.size());while(litPrev.hasPrevious()){System.out.print(litPrev.previous()+" ");}System.out.println();}