Version 1 had quite a few problems that i didnt think about. A lot of them were pointed out in the replies. I tried to correct them as best as i could to make this code.

However , I'm having some doubts regarding what to do while implementing the Collection interface. Mainly in that if i implement Collection , a lot of the methods in it are similar to what i'v already coded up. like add() vs enqueue() . In such cases , i suppose the best way out will be to make my methods private , and call them from inside their respective Collection implementations ?

Also, I was using System.arraycopy() previously , but in my tests , i found that it wasnt ideal for a circular array. Case in point :

adding : e
head : 5 tail : 5 , size : 12
a b c d e f g h i j k l 

adding : f
resizing array to size: 24
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at ResizingCircularArray.resize(ResizingCircularArray.java:16)
    at ResizingCircularArray.enqueue(ResizingCircularArray.java:33)
    at ResizingCircularArray.main(ResizingCircularArray.java:105)

This came up because : head + size > source length , and resulted in IndexOutOfBounds exception. So i made something similar that works with cicular array.

// Modified version of System.arraycopy() to work with circular array.
    private void arrayCopy(E[] srcArr , int srcpos , E[] destArr , int destpos , int length){
        for(int index = 0 ; index < length ; index++){
            destArr[index] = srcArr[head++];
            if(head == srcArr.length){
                head = (head % srcArr.length);
            }
        }
    }

However , I'm unsure as to how to include exceptions for ArrayStore in here . docs say that it throws the exception when passed object is not an array. But how do i check for an array ? The instaceof checks for one particular type , like int or String , but mine is generic. A bit confused here.

If i could get some suggestions and help regarding the above problems , and my code in general , would be a big help.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

class ResizingCircularArray<E> {

    private int head = 0;
    private int tail = 0;
    private int size = 0; // a measure of non-null elements in the array
    private E[] arr;

    // Modified version of System.arraycopy() to work with circular array.
    private void arrayCopy(E[] srcArr , int srcpos , E[] destArr , int destpos , int length){
        for(int index = 0 ; index < length ; index++){
            destArr[index] = srcArr[head++];
            if(head == srcArr.length){
                head = (head % srcArr.length);
            }
        }
    }

    private void resize() {
        System.out.println("resizing array to size: " + 2 * size);
        @SuppressWarnings("unchecked")
        E[] tempArr = (E[]) new Object[2 * size];
        arrayCopy(arr, head, tempArr, 0, size);
        head = 0;
        tail = size; // tail point to where the NEXT element will land
        arr = tempArr;
    }

    @SuppressWarnings("unchecked")
    public ResizingCircularArray() {
        arr = (E[]) new Object[3];

    }

    public void enqueue(E item) {
        if (item == null)
            throw new NullPointerException(
                    " adding null values is not allowed ");
        if (size == arr.length) {
            resize();
        }
        if (tail == arr.length) {
            // going round
            tail = (tail % arr.length);
        }
        arr[tail++] = item;
        size++;
        System.out.println("head : " + head + " tail : " + tail + " , size : "
                + size);
    }

    public E dequeue() {
        if (!(size > 0))
            throw new java.util.NoSuchElementException("size is negative");
        E item = arr[head];
        arr[head++] = null;
        if (head == (arr.length)) {
            head = (head % arr.length); // =0
        }
        --size;
        if (size == arr.length / 4) {
            resize();
        }
        System.out.println("head : " + head + " tail : " + tail + " , size : "
                + size);
        return item;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public E sample(int offset) {
        if (offset < 0)
            throw new java.lang.IllegalArgumentException(
                    "provided offset is out of bounds");
        return arr[head + offset];
        /*
         * NOTE : the check for (head+offset)>tail as pointed out by sos will
         * work in case of linear array , Not in case of Circular array because
         * when tail comes around in a circle , tail will be < than head and the
         * above check will create trouble
         */
    }

    public int size() {
        return size;
    }

    public void display() {
        for (E item : arr)
            System.out.print(item + " ");
        System.out.println("\n");
    }

    public static void main(String[] args) {

        ResizingCircularArray<String> r = new ResizingCircularArray<String>();
        String line = null;
        String[] segment, parsed;
        boolean endFlag = false;
        int count = 0;

        try (BufferedReader is = new BufferedReader(new FileReader(
                "CircArrayPoints.txt"))) {
            line = is.readLine();
            segment = line.trim().split(";");
            System.out.println("total commands : " + segment.length);
            for (int i = 0; !segment[i].equals("stop") && !endFlag; i++) {
                parsed = segment[i].split(" ");
                count++;
                switch (parsed[0]) {
                case "enq":
                    System.out.println(count+ ".adding : " + parsed[1]);
                    r.enqueue(parsed[1]);
                    r.display();
                    break;
                case "deq":
                    if (r.isEmpty()) {
                        System.out.println("Empty queue");
                        endFlag = true;
                        break;
                    }
                    // print after checking isEmpty() to make sure
                    // sample(0) doesn't call null etc
                    System.out.println(count+ ".dequeing : " + r.sample(0));
                    r.dequeue();
                    r.display();
                    break;
                case "disp":
                    r.display();
                    break;
                default:
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Files : CircArrayPoints.txt

enq a;enq b;enq c;enq d;enq e;enq f;enq g;enq h;enq i;enq j;enq k;enq l;deq;deq;deq;deq;deq;enq a;enq b;enq c;enq d;enq e;enq f;enq g;enq h;enq i;enq j;enq k;enq l;enq m;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;disp;stop

Edited 3 Years Ago by somjit{}

No time to read your code now.. but...
You will learn an awful lot now from looking at the source code fr the actual API classes (eg how exceptions are handled in arrayCopy) - you should have a source.zip file in your jdk directory which contains it all. I recommend it as a general compendium of "best practice" java code, as well as examples of how best to solve specific problems.
add vs enque - if they are the same why not just use the "standard" Collection method names? If you want both then it's perfectly OK to have one as a one-line cover that just calls the other. The Vector class is a similar case...

ps: See also source code for Arrays.copyOf - ArrayStore is an unchekced exception that the VM will throw if the source and target arrays contain incompatible types, so you don't have to do anything to implement it

Edited 3 Years Ago by JamesCherrill

Hey thanks for the location of the api codes! As retarded as it may sound , i searched a lot for them on the net thinking it may be there , but didnt find anything. All the time it was under my noses it seems.. !

This article has been dead for over six months. Start a new discussion instead.