最近一直在研究数据结构与算法,涉及到自定义数组和队列,感觉对JDK源代码的底层功能实现学习有一定的帮助,故作此总结,以供参考。
ps:JDK的源代码更加复杂,我的自定义数组列表和队列只是一些简单的逻辑实现。
1.自定义数组列表(MyArrayList.java)
package com.BlueStarWei.arrayList; /** * * show all fields and method,please click "ctrl + o" * * * 开发过程遇到的问题: * 1. 传入下标(index)未考虑越界情况 * 一定要校验指针是否越界 * 2. 当容量耗尽后,如何拓展新的空间 * 添加一个变量(hasInitCapacity),用于判断数组的创建方式。 * 如果是通过无参构造方式创建(hasInitCapacity = false),每次扩展容量的时候在原有数组长度的基础上增加拓展长度。 * * @author HuWei * * @param <E> */ public class MyArrayList<E> { /** * The default capacity while use constructor form superClass */ private final int DEFUALT_CAPACITY = 10; /** * The expending capacity while arr that is generated via constructor form superClass is full */ private final int ADD_CAPACITY = DEFUALT_CAPACITY / 2; /** * The array to store elements */ private E[] arr; /** * The length of element to be stored into arr */ private int size; /** * check whether is the queue generated by constructor with initCapacity */ private boolean hasInitCapacity; public MyArrayList() { arr = (E[]) new Object[DEFUALT_CAPACITY]; hasInitCapacity = false; } public MyArrayList(int initCapacity){ arr = (E[]) new Object[initCapacity]; hasInitCapacity = true; } /** * * @return * the length of array */ public int size() { return size; } /** * let element insert to arr * if MyArrayList is generated via constructor form superClass and the capacity is full,then expand capacity * @param element * the element to insert * @return index * the index of the element to insert */ public int add(E element){ //expend capacity if(!hasInitCapacity && size == arr.length){ E[] arr2 = arr; arr = (E[]) new Object[arr.length + ADD_CAPACITY]; for (int i = 0; i < arr2.length; i++) { arr[i] = arr2[i]; } } arr[size] = element; return size++; } /** * * @param index * the index of the element to replace * @param element * the element to replace * @return * the element to be replaced */ public E update(int index, E element){ checkArange(index); E old = arr[index]; arr[index] = element; return old; } /** * * @param index * the index of the element to be removed * @return * the element to be removed */ public E remove(int index){ checkArange(index); E element = arr[index]; if(index == size - 1){ arr[index] = null; } for (int i = index; i < size; i++) { arr[i] = arr[i+1]; } size--; return element; } /** * * @param index * the index of the element to get * @return * the element to get */ public E get(int index){ return arr[index]; } /** * check whether index is out of bounds * @param index */ private void checkArange(int index){ if(index < 0 || index >= size){ throw new ArrayIndexOutOfBoundsException(); } } @Override public String toString() { StringBuilder result = new StringBuilder(); result.append("["); for (int i = 0; i < size; i++) { result.append(arr[i]); if(i != size - 1){ result.append(","); } } result.append("]"); return result.toString(); } }
2. 自定义队列(MyQueue.java)
package com.BlueStarWei.queue; /** * 开发终于到的问题: * 1. 元素poll完(元素实际上并没有从数组中删除,只是将头指针向后移)之后,再次添加数据的时候如何从头开始? * 判断queue有效的元素是否为空,如果为空,将头指针和尾指针重置到数组最前端 * * 优化: * 1. 与自定义数组列表相比,在创建队列的时候没有队列的类型为任意集合(E)类型,而是指定为Object[]类型, * 只有在元素返回时,返回为任意集合(E)类型 * * @author HuWei * * @param <E> */ public class MyQueue<E> { /** * The default capacity while use constructor form superClass */ private final int DEFUALT_CAPACITY = 10; /** * The expending capacity while arr that is generated via constructor form superClass is full */ private final int ADD_CAPACITY = DEFUALT_CAPACITY / 2; /** * store the element */ private Object[] queue; /** * the head pointer of queue *it always point the first alive element */ private int front; /** * the end pointer of queue * it always point the last alive element */ private int end; /** * the real size of queue */ private int size; /** * check whether is the queue generated by constructor with initCapacity */ private boolean hasInitCapacity; /** * generate a queue whose default size is DEFUALT_CAPACITY */ public MyQueue() { queue = new Object[DEFUALT_CAPACITY]; hasInitCapacity = false; end = -1; } /** * generate a queue whose default size is initCapacity */ public MyQueue(int initCapacity){ queue = new Object[initCapacity]; hasInitCapacity = true; end = -1; } /** * store element to queue * @param element * the element to be stored */ public void push(E element){ if(!hasInitCapacity && size == queue.length){ Object[] queue2 = queue; queue = new Object[size + ADD_CAPACITY]; for (int i = 0; i < queue2.length; i++) { queue[i] = queue2[i]; } } queue[++end] = element; size++; } /** * remove the first alive element in queue * while queue is queue is empty, set front and end pointer point the queue's head * * @return * the element to be remove */ public E poll(){ E element = (E)queue[front++]; size--; if(isEmpty()){ front = 0; end = -1; } return element; } /** * get the first alive element in queue * @return * the element to be returned */ public E peek(){ E element = (E)queue[front]; if(isEmpty()){ element = null; } return element; } /** * check whether is queue empty. * * @return * */ public boolean isEmpty(){ if(size == 0){ return true; }else { return false; } } /** * get the size of queue * * @return * the size of queue */ public int size(){ return size; } }