目录
一、顺序表与线性表的概念
1、顺序表
2、线性表
二、Java里的集合类之ArrayList
1、ArrayList与顺序表
2、认识ArrayList
1.构造方法
2.常用方法
3.遍历ArrayList的几个方法
4.扩容机制
三、模拟实现ArrayList
1、字段
2、构造方法
3、常用方法
1.判满
2.判空
3.遍历
4.是否存在
5.新增
6.指定位置插入
7.删除指定下标元素
8.删除第一次出现的key
9.获取某元素的下标
10.获取指定下标位置的元素
11.指定的下标位置更改指定值
12.指定值最后出现的下标
13.获取有效数据个数
14.置空顺序表
一、顺序表与线性表的概念
1、顺序表
是用一段物理地址连续的的存储单元依次存储数据的线性结构,一般情况下采用数组进行数据存储,删除或插入数据时需要移动数据,它物理地址连续,存储单元连续,数据元素的存储连续,不能跳跃式的存储,一般采用数组存储,在数组上完成增删查改等功能
2、线性表
是具有n个相同特性的数据元素的有限序列,在逻辑上连续但是在物理地址上不一定连续,常见的线性表有:链表、栈、队列
二、Java里的集合类之ArrayList
1、ArrayList与顺序表
ArrayList实现了RandomAccess接口所以,ArrayList支持随机访问;他也实现了Cloneable接口,所以他支持clone;他也实现了Serializable接口,说明他可以支持序列化,与老版本的Vector不同的是,ArrayList不是线程安全的,即他在单线程下可以使用但是在多线程里不能直接使用,在多线程且读数据次数多于写数据的情况下更推荐使用CopyOnWriteArrayList,或者使用ArrayList时自己加锁也可以,最后ArrayList底层是数组是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表
2、认识ArrayList
1.构造方法
构造方法 | 说明 |
ArrayList() | 无参构造方法,长度为默认值0 |
ArrayList(Collection<? extends E> c) | 使用Collection构建 |
ArrayList(int initialCapacity) | 指定其初始长度 |
2.常用方法
boolean add(E e) | 在结尾插入数据e |
void add(int index,E e) | 将数据插到指定的下标位置 |
boolean addAll(Collection<? extends E> c) | 将数据c的元素尾插入当前顺序表 |
E remove(int index> | 删除指定下标元素 |
boolean remove(Object o) | 删除第一次出现的元素o |
E get(int index) | 获取指定下标的元素 |
void clear() | 清空顺序表 |
E set(int index,E e) | 将指定下标位置的元素替换为e |
boolean contains(Object o) | 判断元素o是否存在于当前顺序表 |
int indexOf(Object o) | 返回第一个o所在下标 |
int lastIndexOf(Object o) | 返回最后的o所在下标 |
List<E> subList(int fromIndex,int toIndex) | 截取部分list |
int size() | 获取当前有效数据个数 |
3.遍历ArrayList的几个方法
主要有三种:for循环 foreach 迭代器
public static void main(String[] args) {
//创建实例指定大小
ArrayList<Integer> arrayList = new ArrayList<>(10);
System.out.println(arrayList.size());
//插入数据
for (int i = 0; i < 10; i++) {
arrayList.add(i);
}
//遍历
for (int i = 0; i < arrayList.size(); i++) {
System.out.print(arrayList.get(i) +" ");
}
System.out.println("\n---------------------");
for (Integer x:arrayList) {
System.out.print(x + " ");
}
System.out.println("\n---------------------");
Iterator<Integer> it = arrayList.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}
}
4.扩容机制
1.无参构造扩容
构造时不传入参数,默认长度为0
此时数组为空,调用add进行插入数据
此时由于无参构造,所以此时的size=0,size+1为1,带着参数进入enSureCapacityInternal方法
此时进入 enSureCapacityInternal方法后又进入calculateCapacity(底层的数组,1)
此时返回 DEFAULT——XAPACITY与1的最大值即为10
函数执行完回到 enSureCapacityInternal方法
此时进入ensureExplicitCapacity(10)
此时进入扩容方法
到此处长度扩容为10
2.传入指定长度构造10
此处可以发现,传入指定长度如果满足要求即创建指定长度的数组,如果为0则跟无参构造相同,如果传入值不合法则抛异常
此时若add了10给数据,此时再add即进入扩容
进入了 enSureCapacityInternal方法
又进入calculateCapaciyt
此方法执行完返回11,回到enSureCapacityInternal方法里执行ensureExplictCapacity(11)
此时进入grow进行扩容
综上当使用无参构造时,第一次扩容了10,后续扩容以1.5倍进行
三、模拟实现ArrayList
1、字段
2、构造方法
3、常用方法
1.判满
2.判空
3.遍历
4.是否存在
5.新增
此处值得注意的是,扩容时使用的copyOf方法,在使用时,如果传入的数组为空会空指针异常,或者传入扩容的数值是负数就会抛出异常,所以进行处理
6.指定位置插入
7.删除指定下标元素
8.删除第一次出现的key
9.获取某元素的下标
10.获取指定下标位置的元素
11.指定的下标位置更改指定值
12.指定值最后出现的下标
13.获取有效数据个数
14.置空顺序表