一、前言
对于arraylist集合,其是List接口下的一种数据存储结构,底层由数组组成。本身特点为:查找快,增删慢(原因:因为底层是数组,而数组是需要一个连续的空间,每次的增删就相当于数组的移动和复制,从而效率大大降低。但是在查询上,效率极高。)
二、核心
1. 在翻阅jdk源码之后,其大致可以总结为:
- 进行add方法添加之后,默认值首先为0,其次有一个判断,从而使默认值为10;
- 扩容机制为1.5倍的扩容,采用的是位运算(位运算在java中的效率高);
- 核心代码为
System.arraycopy (objects,0,temp,0,objects.length);
其作用为数组的复制,参数依次为:源对象,源对象起始位置,目标对象,目标对象起始位置,拷贝元素个数。
2. ArrayList非线程安全,如果多个线程同时对同一个arraylist更改数据的话,会导致数据不一致或者数据污染,如果出现线程不安全操作的时候,arraylist尽可能的抛出concurrentModifycationException防止数据异常。如果想保证线程安全,可以使用vector...
三、手写arraylist的简单实现
package Arraylist;
import sun.applet.Main;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Objects;
public class MyArraylist {
//数组容器,jdk中默认大小为10
private Object[] objects = new Object[3];
//初始大小
private int size = 0;
//数组的添加方法
public void add(Object obj){
//判断是否索引大于容器容量,如果大于,则扩容(新建数组)arraylist支持的是1.5倍扩容
if(size >= objects.length){
//jdk中采用的是位运算,区别在于位运算效率更高
Object[] temp = new Object[size*3/2 + 1];
//核心方法,相当于数组的复制
System.arraycopy (objects,0,temp,0,objects.length);
objects = temp;
}
objects[size] = obj;
size++;
}
//集合的长度
public int length(){
return size;
}
//集合指定元素的赋值
public void set(int index,Object obj) throws Exception {
if(index <= size && index >= 0){
objects[index] = obj;
}else{
throw new Exception ("数组下标越界");
}
}
//获取指定下标的元素
public Object getValue(int index) throws Exception {
if(index > size || index < 0){
throw new Exception ("数组下标越界");
}
return objects[index];
}
//删除指定下标的元素
public Object remove(int index) throws Exception {
if(index > size || index < 0){
throw new Exception ("数组下标越界");
}
//要返回的元素
Object obj = objects[index];
//从删除元素的后一个位置开始复制,复制newIndex个(相当于数组的自我复制)
int newIndex = objects.length-1-index;
System.arraycopy (objects,index+1,objects,index,newIndex);
//复制完后,长度要减一
size--;
return obj;
}
//清空集合
public void clear(){
size = 0;
objects = new Object[3];
}
//测试方法
public static void main(String[] args) throws Exception {
MyArraylist ma = new MyArraylist ();
ma.add ("1");
ma.add ("2");
ma.add ("3");
ma.add ("4");
// ma.clear ();
// System.out.println (ma.size);
// System.out.println (ma.remove (2));
for (int i = 0;i < ma.length ();i++){
Object obj = ma.getValue (i);
System.out.println (obj);
}
}
}
四、优化
- 如果在初始化的时候知道ArrayList的初始容量,请一开始就指定容量ArrayList<String> list = new ArrayList<String>(20);
- 如果一开始不知道容量,中途才得知,请调用list.ensureCapacity(20);来扩充容量;
- 如果数据已经添加完毕,但仍需要保存在内存中一段时间,请调用list.trimToSize()将容器最小化到存储元素容量,进而消除这些存储空间浪费。