前言
数组是线性数据结构的典型代表,不仅在我们的日常开发中使用十分广泛,而且在JDK源码中也有很多它的身影,所以数组的重要性不言而喻。本文接下来会讲述如何将原生的数组封装成支持泛型并可以自动扩容的线性数据结构,这里对于数组的基础使用部分就不赘述了。
1.泛型支持
由于原生的数组对泛型并不支持,可以采用Object类型数组来进行数据的存储,然后使用类型强转的方式提供泛型支持。
public class CustomArray<E> {
//数组大小
private int size;
//内部封装数组
private E[] array;
//默认数组容量大小
private static final int DEFAULT_CAPACITY = 100;
//数组的负载因子
private static final double loadFactor = 0.75F;
/**
*初始化自定义数组
*@param capacity 数组容量
*/
public CustomArray(int capacity){
size = 0;
array = (E[]) new Object[capacity];
}
}
2.元素添加
可以在执行下标位置进行元素的添加,注意对输入下标进行检查,防止数组下标越界异常
/**
* 添加元素
* @param index 下标
* @param element 元素
*/
public void add(int index,E element){
//检查插入元素数组下标
checkForIndexAdd(index);
//插入下标位置及后的元素处理
for (int i = size -1; i >= index ; i--) {
array[i+1] = array[i];
}
//插入元素
array[index] = element;
//数组大小+1
size++;
//数组容量检查,如果超出临界容量进行自动扩容
...
}
3.动态扩容
定义一个数组的负载因子,计算数组存储数据量的临界值,当超过该临界值的时候进行自动扩容
/**
* 检查数组的容量
*/
private void checkForCapacity(){
if(size > array.length*LOAD_FACTOR)
resize(2*array.length);
}
/**
* 数组扩容
* @param newCapacity 数组扩容后的容量
*/
private void resize(int newCapacity){
array = Arrays.copyOf(array, newCapacity);
}
4.元素查找
可以在执行下标位置进行数据查找,对输入下标进行检查
/**
* 查找数据
* @param index 下标
* @return
*/
public E findByIndex(int index){
//检查数据下标
checkForIndex(index);
E element = array[index];
return element;
}
5.元素删除
可以在执行下标位置进行数据删除,对输入下标进行检查
/**
* 删除元素
* @param index
* @return
*/
public E del(int index){
//检查下标
checkForIndex(index);
E delElement = array[index];
//被删除下标后面的元素前移
for (int i = index; i < array.length; i++) {
array[index] = array[index + 1];
}
array[array.length - 1] = null;
size--;
return delElement;
}
总结
这里我们基于原生的数组开发了一个自定义的数组结构,屏蔽了原生数组不支持泛型以及动态扩容的缺陷,其实ArrayList的底层也是基于数组实现,同时也支持上述的功能点,并且对一些地方有更好的实现,有兴趣的话可以查看一个ArrayList源码,可以对数组结构有一个更全面的认识。