您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息
三六零分类信息网 > 渭南分类信息网,免费分类信息发布

分析Java ArrayQueue源码

2024/6/21 2:28:24发布11次查看
arrayqueue内部实现在谈arrayqueue的内部实现之前我们先来看一个arrayqueue的使用例子:
public void testqueue() { arrayqueue<integer> queue = new arrayqueue<>(10); queue.add(1); queue.add(2); queue.add(3); queue.add(4); system.out.println(queue); queue.remove(0); // 这个参数只能为0 表示删除队列当中第一个元素,也就是队头元素 system.out.println(queue); queue.remove(0); system.out.println(queue);}// 输出结果[1, 2, 3, 4][2, 3, 4][3, 4]
首先arrayqueue内部是由循环数组实现的,可能保证增加和删除数据的时间复杂度都是,不像arraylist删除数据的时间复杂度为。在arrayqueue内部有两个整型数据head和tail,这两个的作用主要是指向队列的头部和尾部,它的初始状态在内存当中的布局如下图所示:
因为是初始状态head和tail的值都等于0,指向数组当中第一个数据。现在我们向arrayqueue内部加入5个数据,那么他的内存布局将如下图所示:
现在我们删除4个数据,那么上图经过4次删除操作之后,arrayqueue内部数据布局如下:
在上面的状态下,我们继续加入8个数据,那么布局情况如下:
我们知道上图在加入数据的时候不仅将数组后半部分的空间使用完了,而且可以继续使用前半部分没有使用过的空间,也就是说在arrayqueue内部实现了一个循环使用的过程。
arrayqueue源码剖析构造函数public arrayqueue(int capacity) { this.capacity = capacity + 1; this.queue = newarray(capacity + 1); this.head = 0; this.tail = 0;}@suppresswarnings("unchecked")private t[] newarray(int size) { return (t[]) new object[size];}
上面的构造函数的代码比较容易理解,主要就是根据用户输入的数组空间长度去申请数组,不过他具体在申请数组的时候会多申请一个空间。
add函数public boolean add(t o) { queue[tail] = o; // 循环使用数组 int newtail = (tail + 1) % capacity; if (newtail == head) throw new indexoutofboundsexception("queue full"); tail = newtail; return true; // we did add something}
上面的代码也相对比较容易看懂,在上文当中我们已经提到了arrayqueue可以循环将数据加入到数组当中去,这一点在上面的代码当中也有所体现。
remove函数public t remove(int i) { if (i != 0) throw new illegalargumentexception("can only remove head of queue"); if (head == tail) throw new indexoutofboundsexception("queue empty"); t removed = queue[head]; queue[head] = null; head = (head + 1) % capacity; return removed;}
从上面的代码当中可以看出,在remove函数当中我们必须传递参数0,否则会抛出异常。而在这个函数当中我们只会删除当前head下标所在位置的数据,然后将head的值进行循环加1操作。
get函数public t get(int i) { int size = size(); if (i < 0 || i >= size) { final string msg = "index " + i + ", queue size " + size; throw new indexoutofboundsexception(msg); } int index = (head + i) % capacity; return queue[index];}
get函数的参数表示得到第i个数据,这个第i个数据并不是数组位置的第i个数据,而是距离head位置为i的位置的数据,了解这一点,上面的代码是很容易理解的。
resize函数public void resize(int newcapacity) { int size = size(); if (newcapacity < size) throw new indexoutofboundsexception("resizing would lose data"); newcapacity++; if (newcapacity == this.capacity) return; t[] newqueue = newarray(newcapacity); for (int i = 0; i < size; i++) newqueue[i] = get(i); this.capacity = newcapacity; this.queue = newqueue; this.head = 0; this.tail = size;}
在resize函数当中首先申请新长度的数组空间,然后将原数组的数据一个一个的拷贝到新的数组当中,注意在这个拷贝的过程当中,重新更新了head与tail,而且并不是简单的数组拷贝,因为在之前的操作当中head可能已经不是了0,因此新的拷贝需要我们一个一个的从旧数组拿出来,然后放到新数组当中。下图可以很直观的看出这个过程:
以上就是分析java arrayqueue源码。的详细内容。
渭南分类信息网,免费分类信息发布

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录