Since the underlying data-structure used here is an array , which is itself iterable via for-each() , i'm wondering how much benefit implementing Iterable will provide here.
I would appreciate if someone could review my code and suggest any further improvements.

Code:

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;

    private void resize() {
        System.out.println("resizing array to size: " + 2 * size);
        @SuppressWarnings("unchecked")
        E[] tempArr = (E[]) new Object[2 * size];
        System.arraycopy(arr, head, tempArr, 0, size);
        head = 0;
        tail = head + (size - 1);
        arr = tempArr;
    }

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

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

    public E dequeue() {
        if (size == 0)
            throw new java.lang.NullPointerException("size = 0");
        if (size == arr.length / 4) {
            resize();
        }
        E item = arr[head];
        arr[head++] = null;
        size--;
        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(
                    "negative index not allowed");
        return arr[head + offset];
    }

    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;

        try (BufferedReader is = new BufferedReader(new FileReader(
                "CircArrayPoints.txt"))) {
            line = is.readLine();
            segment = line.trim().split(";");
            for (int i = 0; !segment[i].equals("stop") && !endFlag; i++) {
                parsed = segment[i].split(" ");
                switch (parsed[0]) {
                case "enq":
                    System.out.println("adding : " + parsed[1]);
                    r.enqueue(parsed[1]);
                    r.display();
                    break;
                case "deq":
                    System.out.println("dequeing : " + r.sample(0));
                    if (r.isEmpty()) {
                        System.out.println("Empty queue");
                        endFlag = true;
                        break;
                    }
                    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;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;deq;disp;stop

Recommended Answers

All 8 Replies

Iterable would be a good thing so you can use the enhanced for/each loop with your data structure. For the absolute pinnacle of professionalism implement the whole Collection interface.
Frankly I think your code is very good.

Minor comments:

head = 0;
tail = head + (size - 1);

head is unnecessary in the second statement.

throw new java.lang.IllegalArgumentException

java.lang is always imported; remove the full qualification.

    if (size == 0)
        throw new java.lang.NullPointerException("size = 0");

NPE is not the correct exception to throw here; maybe NoSuchElementException?

Your sample method is missing a check wherein head+offset can go beyond tail.

More importantly, why are you calling it circular if the capacity is pretty much unbounded + I don't see any sort of wrapping going on here.

implement the whole Collection interface

  1. i dont know how to do that
  2. i dont really know what that will result in. If you could provide some examples , would be great.

Frankly I think your code is very good.

Thank you ! :)

The Collection interface is documented in the API doc, so you can read the definitions of methods that it includes. What it gives you is the capability to use your ResizingCircularArray just like you can use ArrayList or LinkedList etc as in
Collection<String> myData = new ArrayList<>();
(etc)
change to
Collection<String> myData = new ResizingCircularArray<>{};
... and the rest of the code will work without any further changes

@ ~s.o.s~

head is unnecessary in the second statement.

I kept that extra head to make it easier to understand later on , or for someone else viewing my code.

maybe NoSuchElementException?

Eclipse auto generation :| i intended it to be NSEE.

Your sample method is missing a check wherein head+offset can go beyond tail.

Wow ! i didnt even think of that.

Regarding the circular part , right again ! I felt i was making it circular by virtue of the pop from head , and push to tail , and keeping a tab on the size constantly , But now that you mention it , I really dont have any circular part in it. I'll post again with the 3 corrections. Thanks a lot !

Collection<String> myData = new ResizingCircularArray<>{};

So i can pass it anywhere a Collection<E> is expected .... nice !

Yes, exactly that. It's really nice.
OK, it's not necessary, but if I were marking this as an assignment I would give a whole heap of bonus points for doing that.

An update : As sos pointed out , although i call it a circular buffer , its really a linear one. But lets compare what i do , and what a circular array would have done :

Similarities: A cicular array would keep check of size via the difference between the location of Head and tail , I'm doing basically the same i think , perhaps in a different way.

Dis-similarities: I didnt provide any way for the tail to move past the last position in the array , and occupy the null positions left off where pops occured from the head. If i do that part , I think i'll make it circular ?

anything else i'm missing something ?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.