数据结构之Java实现底层ArrayList

 数据结构是算法的基础和计算机应用的基础,第一个实现的是动态数组,对应于Java的ArrayList,没有它做得那么好,但对于底层实现原理可以有一个初步掌握。以下是具体代码实现:

//此数组类支持泛型
public class Array<E> {
 private E[] data; //声明保存数据的数组
 private int size;   //声明数组的大小即存储了多少个元素
 //有参构造函数需要提供数组初始容量,即数组能够装多少个元素
 public Array(int capacity) {
  data = (E[])new Object[capacity]; //根据参数开辟相应空间的数组
  size = 0;                         //初始大小为0
 }
 
 public Array() {                      //无参构造函数默认数组容量为10
  this(10);
 }

 public Array(E[] arr) {      //有参构造函数,以输入素组生成生成数组
  data = (E[])new Object[arr.length];
  for(int i = 0; i < arr.length; i++)
   data[i] = arr[i];
  size = arr.length;
 }
 
 //获取数组大小
 public int getSize() {
  return size;
 }
 //获取数组容量
 public int getCapacity() {
  return data.length;
 }
 //判断数组是否为空
 public boolean isEmpty() {
  return size == 0;
 }
 //添加元素,根据索引,将指定元素插到相应位置,支持动态添加
 public void add(int index, E e) {
  //判断索引合法性
  if(index < 0 || index > size)
   throw new IllegalArgumentException("Add failed.Require index >=0 and index <= size.");
  //如果数组尺寸等于数组容量,表明数组已满,需要扩容,大小为现在容量的2倍
  if(size == data.length)
   resize(2 * data.length);
  
  //从数组最后一个元素往前遍历,将元素依次往后挪一个
  for(int i = size - 1; i >= index; i--) {
   data[i + 1] = data[i];
  }
  data[index] = e;            //将指定位置的元素保存到相应位置
  size++;                     //维护size,添加一个元素需要加1
 }
 //向数组末端添加一个元素
 public void addLast(E e) {
  add(size, e);
 }
 //向数组头部添加一个元素
 public void addFirst(E e) {
  add(0, e);
 }
 
 //根据索引获取元素
 public E get(int index) {
  if(index < 0 || index >=size)
   throw new IllegalArgumentException("Get failed.Index is illegal.");
  return data[index];
 }
 
 //根据索引修改元素值
 public void set(int index, E e) {
  if(index < 0 || index >=size)
   throw new IllegalArgumentException("Set failed.Index is illegal.");
  data[index] = e;
 }
 
 //判断数组中是否包含输入的元素
 public boolean contain(E e) {
  //遍历整个数组,判断数组中元素是否与输入元素相等
  for(int i = 0; i < size; i++) {
   if(data[i].equals(e))
    return true;
  }
  return false;
 }
 
 //根据输入元素查找下表值
 public int find(E e) {
  for(int i = 0; i < size; i++) {
   if(data[i].equals(e))
    return i;
  }
  return -1;
 }
 
 //根据索引删除相应元素
 public E remove(int index) {
  if(index < 0 || index >=size)
   throw new IllegalArgumentException("Remove failed.Index is illegal.");
  E ret = data[index];    //保存待删的元素
  //从需要删除的元素下一个开始遍历,元素往前挪一格
  for(int i = index + 1; i < size; i++) {
   data[i - 1] = data[i];
  }
  size--;                 //维护size,需要减一个
  data[size] = null;    
  
  //如果数组元素减少到容量的1/4,可以将数组容量缩减为容量1/2
  if(size == data.length / 4 && data.length /2 != 0) {
   resize(data.length / 2);
  }
  
  return ret;
 }
 //从头部删除元素
 public E removeFirst() {
  return remove(0);
 }
 //从末尾删除元素
 public E removeLast() {
  return remove(size - 1);
 }
 //根据相应的元素的值删除元素
 public void removeElement(E e) {
  int index = find(e);
  if(index != -1)
   remove(index);
 }
 //重写toStirng方法,方便观察
 @Override
 public String toString() {
  StringBuilder res = new StringBuilder();
  res.append(String.format("Array: size = %d, capacity = %d\n", size, data.length));
  res.append('[');
  for(int i = 0; i < size; i++) {
   res.append(data[i]);
   if (i != size - 1) {
    res.append(", ");
   }
  }
  res.append(']');
  return res.toString();
 }
 //数组容量重整函数,此函数只需内部使用,外部不可见,将其私有
 private void resize(int newCapacity) {
  //根据传入容量申明新数组
  E[] newData = (E[]) new Object[newCapacity];
  //遍历数组将原数组元素保存到新数组中
  for(int i = 0; i < size; i++) {
   newData[i] = data[i];
  }
  //将原数组指向新数组,完成操作
  data = newData;
 }

 //交换数组中两个元素位置
 public void swap(int i, int j) {
  //判断索引合法性
  if(i < 0 || i >= size || j < 0 || j >= size)
   throw new IllegalArgumentException("Index is illegal.");
  //实施交换
  E temp = data[i];
  data[i] = data[j];
  data[j] = temp;
 }
}

下面是测试程序

public class Main {

 public static void main(String[] args) {
  
  Array<Integer> arr = new Array<>();
  for(int i = 0; i < 10; i++) {
   arr.addLast(i);
  }
  System.out.println(arr);
  
  arr.add(1, 100);
  System.out.println(arr);
  
  arr.addFirst(-1);
  System.out.println(arr);
  
  arr.remove(2);
  System.out.println(arr);
  
  arr.removeElement(4);
  System.out.println(arr);
  
  arr.removeFirst();
  System.out.println(arr);
   }
 }

结果为:

Array: size = 10, capacity = 10
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array: size = 11, capacity = 20
[0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array: size = 12, capacity = 20
[-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array: size = 11, capacity = 20
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array: size = 10, capacity = 20
[-1, 0, 1, 2, 3, 5, 6, 7, 8, 9]
Array: size = 9, capacity = 20
[0, 1, 2, 3, 5, 6, 7, 8, 9]

其他结果就不一一测试,能够实现ArrayList基本功能

猜你喜欢

转载自blog.csdn.net/zhangjun62/article/details/82720572