需要传入数组大小
定义了头指针和尾指针
我的:
public int Maxsize;
private int front;
private int rear;
private Object[] Arr;
public ArrQueue(int ArrMaxsize) {
Maxsize = ArrMaxsize;
Arr = new Object[Maxsize];
front = -1;
rear = -1;
}
最初,头指针和尾指针都指向-1
Java jdk:
//它也是传入数组的大小,并且有异常提示
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
入队
我的:
public void In_ArrQueue(Object obj){
if(rear >= Maxsize-1){ //超界
System.out.println("队满!!!");
}
else{
rear++; //队尾指针上移
Arr[rear] = obj; //元素加到队尾(后进后出)
}
}
Java jdk包里面的就牛逼了,它用到了资源申请算法。。。
Java jdk:
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e; //元素入队
return true;
}
后面的一大堆方法全是关于申请合理的数组容量的
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//minCapacity 就是需要的最小的容量
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //若数组为空
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //分配大小为10
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0) //需要的容量比拥有的大(添加数组后若越界)
grow(minCapacity); //增加拥有的容量
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); //相当于oldCapacity的1.5倍
if (newCapacity - minCapacity < 0) //如果新容量比需要的还要小
newCapacity = minCapacity; //赋值
if (newCapacity - MAX_ARRAY_SIZE > 0) //合理性检查
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) { //检测异常
//小于0代表minCapacity溢出
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
下面来对比一下性能(莫名感觉很惭愧。。。):
//仍然是比较加入一千万个点的时间
public static void main(String[] args) {
long S = 0;
for (int n = 0; n < 10; n++) {
long start = System.currentTimeMillis();
ArrayList<Object> arrayList = new ArrayList<>();
for (int i = 0; i < 10000000; i++) {
arrayList.add(i);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
long S1 = end - start;
S = S + S1;
}
System.out.println("平均时间" + S / 10);
我的:
系统:
- 我的add方法之所以快,是因为我一开始就定义好了数组的长度,这样其实是浪费了大量的空间
- 系统通过资源申请算法,很完美的控制了空间资源分配,实现了利用数组创建队列不需要定义长度
- (今天的操作系统课刚好讲了银行家算法中的资源请求算法,这就用上了,,,)
出队
我的:
public void Out_ArrQueue(){
if(rear == front){
System.out.println("队空!!!");
}
else{
front++; //出队时队首指针上移 (假溢出的部分根源)
Arr[front]=null;
}
}
Java jdk:
E elementData(int index) { //返回index位置的元素
return (E) elementData[index];
}
private void rangeCheck(int index) { //检测范围异常
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
public E remove(int index) { //jdk中要传入一个下标
rangeCheck(index); //是否超界
modCount++;
E oldValue = elementData(index); //获取该位置元素
int numMoved = size - index - 1; //被删除位置的元素之后的元素要前移
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved); //拷贝移动元素
elementData[--size] = null; //如果后面没要移的元素,说明是个尾节点
return oldValue; //返回要删除的值(Object a = arrayList.remove(i))
}
分析完系统的代码,下面的测试根本就没有必要去测了,,,我感觉无比惭愧,自己写的代码就是渣。。。
我的运行时间(一千万数):
系统运行时间(十万个数):
- 系统是从指定位置删除元素的
查询
我的:
public void Find(int index){
System.out.println(Arr[index]);
}
Java jdk:
public E get(int index) {
rangeCheck(index); //检测是否越界
return elementData(index); //返回值
}
- 查询功能,因为大家用的都是数组,所以就比较简单,查询就很快
- Java jdk多了一个检测异常
- 以后写代码尽量养成这种检测异常的习惯
一千万个点:
添加元素,利用了资源申请算法
删除元素,系统可以从指定位置删除
每一种方法,系统都有异常检测