/** * Adds a new element to the end of the list and returns it. If the inner array isn't large enough * then it will grow. * @return instance at the tail */ public T grow() { if( size >= data.length) { T a = createInstance(); add(a); return a; } else { T a = data[(start+size)%data.length]; if( a == null ) { data[(start+size)%data.length] = a = createInstance(); } size++; return a; } }
/** * Returns and removes the first element from the queue. * @return first element in the queue */ public T popHead() { T r = data[start]; removeHead(); return r; }
/** * Returns and removes the last element from the queue. * @return last element in the queue */ public T popTail() { T r = tail(); removeTail(); return r; }
@Test public void isEmpty() { CircularQueue<A> alg = new CircularQueue<A>(A.class,3); assertTrue(alg.isEmpty()); alg.add(new A(5)); assertFalse(alg.isEmpty()); alg.removeTail(); assertTrue(alg.isEmpty()); }
@Test public void removeTail() { CircularQueue<A> alg = new CircularQueue<A>(A.class); alg.grow().value = 1; alg.grow().value = 2; alg.removeTail(); assertEquals(1,alg.head().value); assertEquals(1,alg.size()); alg.removeTail(); assertEquals(0, alg.size()); }
@Test public void removeHead() { CircularQueue<A> alg = new CircularQueue<A>(A.class); alg.grow().value = 1; alg.grow().value = 2; alg.removeHead(); assertEquals(2, alg.head().value); assertEquals(1, alg.size()); alg.removeHead(); assertEquals(0, alg.size()); }
@Test public void get() { CircularQueue<A> alg = new CircularQueue<A>(A.class,2); assertEquals(2,alg.data.length); // easy case alg.grow().value = 1; alg.grow().value = 2; assertEquals(1,alg.get(0).value); assertEquals(2,alg.get(1).value); // make there be an offset alg.removeHead(); alg.grow().value = 3; assertEquals(2,alg.data.length); // sanity check assertEquals(2,alg.get(0).value); assertEquals(3,alg.get(1).value); }
@Test public void tail() { CircularQueue<A> alg = new CircularQueue<A>(A.class); alg.grow().value = 1; assertEquals(1,alg.tail().value); alg.grow().value = 3; assertEquals(3, alg.tail().value); }
@Test public void add() { CircularQueue<A> alg = new CircularQueue<A>(A.class,3); assertEquals(3,alg.data.length); alg.add( new A(1)); assertEquals(1,alg.data[0].value); assertEquals(1,alg.size); alg.add( new A(2)); assertEquals(1,alg.data[0].value); assertEquals(2,alg.data[1].value); alg.add( new A(3)); alg.add( new A(4)); assertEquals(1,alg.data[0].value); assertEquals(2,alg.data[1].value); alg.data = new A[]{new A(1),new A(2), new A(3)}; alg.size = 3; alg.add( new A(4)); assertEquals(2,alg.data[0].value); assertEquals(3,alg.data[1].value); alg.size = 2; alg.data = new A[3]; alg.add( new A(10)); assertEquals(10,alg.data[0].value); assertEquals(3,alg.size);
@Test public void head_offset() { CircularQueue<A> alg = new CircularQueue<A>(A.class,3); alg.start = 2; alg.size = 0; alg.grow().value = 1; assertEquals(1, alg.head().value); alg.grow().value = 3; assertEquals(1,alg.head().value); }
private void growInnerArray() { T a[] = (T[]) Array.newInstance(type, nextDataSize()); System.arraycopy(data,start,a,0,data.length-start); System.arraycopy(data,0,a,data.length-start,start); start = 0; data = a; }
/** * Adds a new element to the queue. If the queue isn't large enough to store this value then its internal data * array will grow * @param value Value which is to be added */ public void add( T value ) { // see if it needs to grow the queue if( size >= data.length) { growInnerArray(); } data[(start+size)%data.length] = value; size++; }
/** * Adds a new element to the end of the list and returns it. If the inner array isn't large enough * then the oldest element will be written over. * @return instance at the tail */ public T growW() { T a; if( size >= data.length) { a = data[start]; if( a == null ) data[start] = a = createInstance(); start = (start+1)%data.length; } else { a = data[(start+size)%data.length]; if( a == null ) data[(start+size)%data.length] = a = createInstance(); size++; } return a; }
@Test public void growW() { CircularQueue<A> alg = new CircularQueue<A>(A.class,3); alg.growW().value = 1; assertEquals(1,alg.size); alg.growW().value = 2; alg.growW().value = 3; alg.growW().value = 4; assertEquals(4,alg.data[0].value); assertEquals(3,alg.data[2].value); assertEquals(3,alg.size); assertTrue(alg.data.length == 3); }
@Test public void reset() { CircularQueue<A> alg = new CircularQueue<A>(A.class,3); alg.start = 2; alg.size = 5; alg.reset(); assertEquals(0,alg.size); assertEquals(0,alg.start); }
@Test public void grow() { CircularQueue<A> alg = new CircularQueue<A>(A.class,3); alg.grow().value = 1; assertEquals(1,alg.size); alg.grow().value = 2; alg.grow().value = 3; alg.grow().value = 4; assertEquals(1,alg.data[0].value); assertEquals(4,alg.data[3].value); assertEquals(4,alg.size); assertTrue(alg.data.length >= 4); // wrap around case alg = new CircularQueue<A>(A.class,3); alg.size = 2; alg.start = 1; alg.grow().value = 1; assertEquals(1,alg.data[0].value); assertTrue(null == alg.data[1]); assertTrue(null == alg.data[2]); }
@Test public void addW() { CircularQueue<A> alg = new CircularQueue<A>(A.class,3); assertEquals(3,alg.data.length); alg.addW(new A(1)); assertEquals(1,alg.data[0].value); assertEquals(1,alg.size); alg.addW(new A(2)); assertEquals(1,alg.data[0].value); assertEquals(2,alg.data[1].value); assertEquals(2,alg.size); // see if it over writes alg.addW(new A(3)); alg.addW(new A(4)); assertEquals(4,alg.data[0].value); assertEquals(2,alg.data[1].value); assertEquals(3,alg.data[2].value); assertEquals(3,alg.size); assertEquals(1,alg.start); // wrap around case alg.start = 1; alg.size = 2; alg.data = new A[3]; alg.addW(new A(10)); assertEquals(10,alg.data[0].value); assertEquals(3,alg.size); }
@Test public void tail_offset() { CircularQueue<A> alg = new CircularQueue<A>(A.class); alg.start = 2; alg.size = 0; alg.grow().value = 1; assertEquals(1,alg.tail().value); alg.grow().value = 3; assertEquals(3, alg.tail().value); }