你真的知道ArrayList的使用和实现吗?
Posted 爱敲代码的三毛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你真的知道ArrayList的使用和实现吗?相关的知识,希望对你有一定的参考价值。
文章目录
一、ArrayList是什么?
ArrayList 是 Java 集合框架中比较常用的数据结构,底层是一个顺序表也就是一个数组,那么它和数组最大的区别就是数组的长度是定长,而ArrayList 底层的数组是可以自动增长的。同时 ArrayList 实现了List接口。
二、通过源码了解ArrayList常用的方法
1.ArrayList的创建
首先先来了解一下 ArrayList 的创建,我们知道 ArrayList 底层是一个数组。那么它到底是怎么创建的呢?
ArrayList<Integer> arrayList = new ArrayList<>();
要想了解 ArrayList 我们就必须来看源码,
我们发现当只是 new 了一个 ArrayList 的时候,当前的数组大小是0.
2.add方法
如果只是 new 了一个 ArrayList 那么数组大小为0,也就是说只有在第一次插入元素时才为数组分配大小,且大小为10。如果是数组满了的情况下,就会进行1.5倍扩容。java集合中的扩容函数都叫做 grow;
如果在 add 的同时给了下标,如果当前下标和当前下标后有元素就会把这些元素整体整体移动到 当前 index+1 的位置。
注意:add给下标的时候不能给超过当前最后一个元素位置+2以上的位置,也就是说,如果当前数组只有3个元素你就不能给5下标。
3.addAll方法
addAll方法就是把一个元素集合整体添加进来,可以是 ArrayList 也可以是栈或者是队列。只要是实现了 Collection 接口的都可以添加进来。
代码如下(示例):
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(200);
list.addAll(arrayList);
System.out.println(list);
Stack<Integer> stack = new Stack<>();
stack.push(111);
stack.push(222);
list.addAll(stack);
System.out.println(list);
}
运行结果
4.remove方法
使用realme方法需要注意的是,remove方法是存在重载的,如果是 ArrayList 里面放的是整数,那么如果直接指定要删除的是数字,那么这个数字可能会被当做下标。虽然实际开发中 ArrayList 里面一般不会放整数。
代码
代码如下(示例):
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(11);
arrayList.add(66);
System.out.println(arrayList);
arrayList.remove(arrayList.get(2));//返回的是一个对象
arrayList.remove(2);
System.out.println(arrayList);
}
运行结果
因为 get 返回的是一个对象所以可以通过它的返回值来删除对应的值
5.subList方法
可能有有人天真的以为这就是是一个截取嘛,但这个截取是一定要注意的。
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
arrayList.add(5);
arrayList.add(6);
List<Integer> list = arrayList.subList(1,5);
System.out.println("修改前");
System.out.println(arrayList);
System.out.println(list);
System.out.println("修改后");
list.set(2,100);
System.out.println(arrayList);
System.out.println(list);
}
运行结果
这里修改的只是截取之后的 List 里的值,但修改的同时把原来的 ArrayList里的值也修改了。所以一定要注意!
三、模拟实现 ArrayList
我简单的用泛型模拟实现了一个 ArrayList,就是为了更好理解ArrayList源码是怎么实现的。
import java.util.*;
public class MArrayList<E> {
public E[] elem;//只是定义了一个引用
public int usedSize;//有效的数据个数
public MArrayList () {//初始化一个数组
this.elem = (E[])new Object[10];
}
//增容判断
public boolean isFull() {
if(this.elem.length == this.usedSize){
return true;
}
return false;
}
// 在 pos 位置新增元素
public void add(int pos, E data) {
//判断是否需要增容
if(this.isFull()) {
this.elem = Arrays.copyOf(this.elem,this.elem.length*2);
}
//判断pos位置合法性
if (pos < 0 || pos > this.usedSize) {
throw new ArrayIndexOutOfBoundsException("pos位置不合法");
}
//从后往前挪元素
for (int i = this.usedSize; pos < i; i--) {
this.elem[i+1] = this.elem[i];
}
this.elem[pos] = data;
this.usedSize++;
}
// 打印顺序表
public void display() {
for (int i = 0; i < this.usedSize; i++) {
System.out.print(this.elem[i]+" ");
}
System.out.println();
}
// 判定是否包含某个元素
public boolean contains(E toFind) {
for (int i = 0; i < this.usedSize; i++) {
if(this.elem[i].equals(toFind)) return true;
}
return false;
}
// 查找某个元素对应的位置
public int search(E toFind) {
for (int i = 0; i < this.usedSize; i++) {
if(this.elem[i].equals(toFind)) return i;
}
return -1;
}
// 获取 pos 位置的元素
public E getPos(int pos) {
//判断合法性
if(pos < 0 || pos >= this.usedSize) {
throw new ArrayIndexOutOfBoundsException("pos位置不合法");
}
return this.elem[pos];
}
// 给 pos 位置的元素设为 value
public void setPos(int pos, E value) {
//判断合法性
if(pos < 0 || pos >= this.usedSize) {
throw new ArrayIndexOutOfBoundsException("pos位置不合法");
}
this.elem[pos] = value;
}
//删除第一次出现的关键字key
public void remove(E key) {
int ret = search(key);
if(ret == -1) {
System.out.println("关键字key不存在");
return;
}
for (int i = ret; i < this.usedSize-1; i++) {
this.elem[i] = this.elem[i+1];
}
this.usedSize--;
}
// 获取顺序表长度
public int size() {
return this.usedSize;
}
// 清空顺序表
public void clear() {
if (this.size() == 0) return;
for (int i = 0; i < this.elem.length; i++) {
this.elem[i] = null;
}
this.usedSize = 0;
this.elem = null;
}
}
总结
ArrayList刚创建大小是0,只有当添加元素时才会分配一个大小为10的数组,且往后是1.5倍数扩容。以上是关于你真的知道ArrayList的使用和实现吗?的主要内容,如果未能解决你的问题,请参考以下文章