- ArrayList集合底层实质为数组(Object[])
- 它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要扩容,就要将现有数组的数据复制到新的扩容后的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、效率低下。因此,它适合随机查找和遍历,不适合插入和删除。
- 支持多线程,线程不安全
- 存储数据有序可重复,即顺序:添加进去的元素 取得元素的顺序一致,重复:两个对象元素一致
- 支持泛型,指定存储的数据类型(只能传入引用类型包括包装类,不能传入基本数据类型)
package arraybox;
/**
* @Auther Sunshine
* @Date 2020/7/2 9:26
* ArrayList底层原理封装(支持泛型)
*/
public class ArrayBox<T> {
//初始化数组
private Object[] arrayBox;
//默认初始化数组的容量
private static final int DEFAULT_CAPACITY =10;
//有效个数
private int size=0;
//默认构造方法带有默认为10的容量的数组容量
public ArrayBox() {
arrayBox=new Object[DEFAULT_CAPACITY];
}
//构造方法带有指定容量的数组容量
public ArrayBox(int Capacity){
arrayBox=new Object[Capacity];
}
//将ArrayBox集合转换为数组
public Object[] toArray() {
return arrayBox;
}
//获取ArrayBox集合中有效元素的个数
public int Size() {
return size;
}
//添加元素方法
public void add(T element){
//判断数组容量是否够
this.ensureCapacity(size+1);
//将值添加到数组中
arrayBox[size++]=element;
}
//根据索引进行添加元素
public void add(int index,T element){
//判断index索引是否合法
this.checkAddIndex(index);
//判断数组容量是否够用
this.ensureCapacity(size+1);
if (size==0 || index==size){
//如果是第一个添加元素元素或者最后一个添加元素则直接添加
this.add(element);
}else {
//按照指定位置进行添加元素,先将指定索引位置以后元素向后移动一位
for (int i = size-1; i >=index ; i--) {
arrayBox[i+1]=arrayBox[i];
}
//再将指定索引位置进行插入添加
arrayBox[index]=element;
//有效个数+1
size++;
}
}
//获取ArrayBox索引对应的值(取值)
public T getValue(int index){
//判断index索引是否合法
this.checkIndex(index);
return (T)arrayBox[index];
}
//删除ArrayBox内数组中的某个索引的值
public T remove(int index){
//判断index索引是否合法
this.checkIndex(index);
Object oldElementValue=arrayBox[index];
//删除当前索引位置,将数组往前移值
this.deleteElement(index);
return (T)oldElementValue;
}
//清空ArrayBox中所有元素
public void clear(){
for (int i = 0; i <size ; i++) {
arrayBox[i]=null;
}
//有效个数变为0
size=0;
}
//判断ArrayBox集合中是否包含指定元素
public Boolean contains(Object object){
//如果判断返回的索引值大于等于0,则证明包含object,返回true,否则返回false
return this.indexOf(object)>=0;
}
//重写ArrayBox的toString打印方法(StringBuilder拼接)
@Override
public String toString() {
StringBuilder stringBuilder=new StringBuilder("ArrayBox{");
for (int i = 0; i <size ; i++) {
stringBuilder.append(arrayBox[i]);
if(i==size-1){
break;
}
stringBuilder.append(",");
}
stringBuilder.append("}");
return stringBuilder.toString();
}
//判断数组容量是否够
private void ensureCapacity(int minCapacity){
if (arrayBox.length-minCapacity<0){
//数组容量不够,进行扩容
this.exchange(minCapacity);
}
}
//数组容量不够,进行扩容
private void exchange(int minCapacity){
//长度按位与运算,扩容1.5倍
int newLength=arrayBox.length+(arrayBox.length>>1);
if (newLength-minCapacity<0){
//如果扩容1.5倍后还小于最小容量,则用最小容量数作为扩容后的长度
newLength=minCapacity;
}
//数组扩容后,将原数组复制到新数组中
arrayBox = this.copyArray(arrayBox, newLength);
}
//数组扩容后,将原数组复制到新数组中
private Object[] copyArray(Object[] oldArray,int newLength){
//创建一个扩容后长度的新数组
Object[] newArray=new Object[newLength];
for (int i = 0; i <oldArray.length ; i++) {
//将旧数组中的元素赋值给新数组
newArray[i]=oldArray[i];
}
return newArray;
}
//判断index索引是否合法
private void checkIndex(int index){
if (index<0 || index>=size){
throw new ArrayBoxOutOfBoundException("当前size有效元素:"+size+"--你写入的index:"+index);
}
}
//判断添加元素index索引是否合法
private void checkAddIndex(int index){
if (index<0 || index>size){
throw new ArrayBoxOutOfBoundException("当前size有效元素:"+size+"--你写入的添加元素的index:"+index);
}
}
//删除当前索引位置,将数组往前移值
private void deleteElement(int index){
//原数组索引往前赋值
for (int i = index; i <size-1 ; i++) {
arrayBox[i]=arrayBox[i+1];
}
//将原数组最后有效个数变为0(末尾元素清空),再将数组有效个数减1------(arrayBox[--size]=0;)
size-=1;
arrayBox[size]=null;
}
private int indexOf(Object object){
//判断传入的值是否为null,再进行遍历查找
if (object==null){
for (int i = 0; i <size ; i++) {
if (arrayBox[i]==null){
//查找到则返回索引
return i;
}
}
}else {
//传入的值不为空,再进行遍历查找
for (int i = 0; i <size ; i++) {
if (object.equals(arrayBox[i])){
//查找到返回索引
return i;
}
}
}
//都没有遍历出则返回-1
return -1;
}
}
异常类
package arraybox;
/**
* @Auther Sunshine
* @Date 2020/7/2 12:24
*/
//设置数组越界自定义异常类
public class ArrayBoxOutOfBoundException extends RuntimeException{
public ArrayBoxOutOfBoundException(String message) {
super(message);
}
public ArrayBoxOutOfBoundException() {
}
}
以上封装只适合for循环遍历,不支持Iterator遍历和增强for循环遍历