I'm new to programming and was tasked with programming a generic circular FIFO queue, without using anything but an underlying array and self-programmed methods. I still don't know how to approach bigger projects like this yet. I managed to program something that technically works, but I need someone brutal to really tear this apart and let me know how I can improve. I try to practice when I can, but I still miss so many obvious things and get stuck constantly. I already submitted this work, but you can refrain from explicit answers anyway. Any tips at all are very much appreciated.
The array needs to be able to double or be halved as needed for more memory or to take up less memory. Then it needs to be able to print everything out.
public class FloatingQueue<T>
{
private T[] theArray;
private static final int initialCap = 10;
private int capacity = initialCap;
private int theHead = 0;
private int theTail = -1;
private int size;
FloatingQueue() {
theArray = (T[]) new Object[ initialCap ];
}
//adds object to the end of the queue and returns true if array is now changed successfully
public boolean offer ( T newData ) {
boolean hasChanged = false;
String changeCheck = this.toString();
size++;
theTail++;
if ( size > capacity ) {
this.doubleUp();
hasChanged = true;
}
if ( size > 1 & theTail == theHead | theArray[0] == null ) {
theTail = returnNullIndex();
}
theArray[theTail] = newData;
if ( this.toString() != changeCheck ) {
hasChanged = true;
}
return hasChanged;
}
//removes and returns first object in the queue
public T poll() {
if ( size == 0 ) {
return null;
}
T temp = theArray[theHead];
theArray[theHead] = null;
size--;
if ( this.size() > 0 )
theHead++;
if ( size != 0 & theArray[theHead] == null ) {
theHead = returnNonNullIndex();
if ( returnNullIndex() > 0 & returnNullIndex() < theTail ) {
theHead = 0;
}
if ( size < capacity / 4 && capacity != 10 ) {
this.downSize();
}
}
return temp;
}
//returns the first object and does not remove it
public T peek() {
T temp;
if ( isEmpty() == false ) {
temp = theArray[theHead];
return temp;
}
return null;
}
//Return number of objects in queue
public int size() {
return size;
}
//returns true if queue is empty
public boolean isEmpty() {
boolean noElements = false;
if ( size() == 0 )
noElements = true;
return noElements;
}
//empties the queue
public void clear() {
for ( int i = 0; i < theArray.length; i++ ) {
if ( theArray == null )
break;
theArray[i] = null;
}
size = 0;
theHead = 0;
theTail = -1;
}
//should hopefully print out the strings in order
public String toString() {
String allElements = "[";
if ( size > 0 )
allElements += theArray[theHead].toString() + ",";
for ( int i = 0; i < capacity; i++ ) {
if ( theArray[i] != null && theArray[i] != theArray[theHead] && theArray[i] != theArray[theTail] ) {
allElements += theArray[i].toString() + ",";
}
}
if ( size > 1 )
allElements += theArray[theTail] + ",";
allElements = (size() == 0) ? allElements : allElements.substring(0, allElements.length()-1);
allElements += "]";
return allElements;
}
//doubles array size and copies into bigger array
private void doubleUp ( ) {
capacity *= 2;
T[] biggerArray = (T[]) new Object[ capacity ];
for (int i = 0; i < theArray.length; i++) {
biggerArray[i] = theArray[i];
}
theArray = biggerArray;
}
//halves underlying array and copies over
private void downSize ( ) {
capacity /= 2;
int smallArrayIndex = 0;
T[] smallerArray = (T[]) new Object[ capacity ];
for ( int i = theHead; i <= theTail; i++ ) {
smallerArray[smallArrayIndex] = theArray[i];
smallArrayIndex++;
}
theHead = 0;
theTail = size - 1;
theArray = smallerArray;
}
//finds first null index
private int returnNullIndex () {
for (int i = 0; i < theArray.length-1; i++) {
if ( theArray[i] == null ) {
return i;
}
}
return -1;
}
//finds non null index
private int returnNonNullIndex () {
for (int i = 0; i < theArray.length-1; i++) {
if ( theArray[i] != null ) {
return i;
}
}
return -1;
}