0

I have an assignment to implement a generic circular buffer. Everything is fine, I only need to do a sort method however I cannot think of a solution to make it generic. Could you please give me a hint? Thank you!

public class CircularBuffer<T> {

public T[] elements = null;

private int capacity = 0;
private int dataStart = 0;
private int dataEnd = 0;   

@SuppressWarnings("unchecked")
public CircularBuffer(int capacity) {
    this.capacity = capacity;
    this.elements = (T[]) new Object[capacity];
}

public boolean isEmpty() {
    return dataStart == dataEnd;
}

public boolean isFull() {
    if (dataStart == 0) {
        return dataEnd == capacity - 1 ;
    }
    return dataStart - dataEnd == 1;
}

public int size() {
    return dataEnd - dataStart;
}

public void put(T t) {
    if (isFull()) {
        throw new RuntimeException("Buffer is full");
    }
    if (dataEnd < capacity) {
        elements[dataEnd] = t;
        dataEnd++;
    }
}

public T get() {
    if (isEmpty()) {
        throw new RuntimeException("Buffer is empty");
    }
    return elements[dataStart++];
}

public Object[] toObjectArray() {
    Object[] newArray = new Object[size()];
    for (int i = dataStart; i < dataEnd; i++) {
        newArray[i] = elements[i];
    }
    return newArray;
}

@SuppressWarnings("unchecked")
public <Q> Q[] toArray(Q[] a) {
    if (a.length < size())
        return (Q[]) Arrays.copyOf(elements, size(), a.getClass());
    System.arraycopy(elements, 0, a, 0, size());
    return a;
}

public List<T> asList(List<T> a) {
    List<T> list = new ArrayList<>(size());
    for (int i = dataStart; i < dataEnd; i++) {
        list.add(elements[i]);
    }
    return list;
}

public void addAll(List<? extends T> toAdd) {
    if (toAdd.size() > capacity - size()) {
        throw new RuntimeException("Not enough space to add all elements");
    }
    else {
        for (int i = 0; i < toAdd.size(); i++) {
            elements[dataEnd] = toAdd.get(i);
            dataEnd++;
        }
    }
}

public void sort(Comparator<? super T> comparator) {
    // TODO
}

}
Kokufuu
  • 145
  • 1
  • 2
  • 7

3 Answers3

1

The simplest option would be to get the contents out as a List, sort it and replace the old contents from the now sorted list.

    public void sort(Comparator<? super T> comparator) {
        // Get them all out - not sure why you have a parameter to `asList`
        List<T> all = asList(Collections.emptyList());
        // Sort them.
        Collections.<T>sort(all);
        // Clear completely.
        dataStart = dataEnd = 0;
        addAll(all);
    }

You will need to change the signature of your class to ensure T is sortable.

public class CircularBuffer<T extends Comparable<T>> {
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • Regarding `asList` : I need to know the type of the list which it will give back. It gets the type form the parameter and creates a list of that type. – Kokufuu Apr 10 '18 at 12:43
  • @Kokufuu - It just does `new ArrayList<>` - ignoring the parameter. Unless you plan to change that - which is fine. – OldCurmudgeon Apr 10 '18 at 13:01
  • please correct me but doesn't ArrayList get the type `T` automaticly into the `<>` ? – Kokufuu Apr 10 '18 at 13:22
  • @Kokufuu - Yes but it gets it from the class generic parameter `T`, not the parameter passed to `asList`. – OldCurmudgeon Apr 10 '18 at 13:25
0

Well,
A) this is not circular - you should reset the indexes dataStart and dataEnd when they pass the capacity. An easy way to do that is by replacing things like:

dataEnd++;

with:

dataEnd = (dataEnd + 1) % capacity;

B) Once you do that, I'm guessing the by "sorting" you mean only the part that is between dataStart to dataEnd. That's not trivial because of the circular nature. I think you'll need to implement one of the sorts on your circular buffer.

Roee Gavirel
  • 18,955
  • 12
  • 67
  • 94
  • regarding A: yes, I know, that was how I originally implemented it however the description for the task says "The put method throws RUNTIME exception if the buffer is full. The buffer is full when the head and the tail points to the same index, but the buffer is not empty". By this I understood it is not really circular. So let's say it is not really circular... how will a sort be generic? – Kokufuu Apr 10 '18 at 12:22
  • You got it correct in the first time regarding the circular. The rest is to complicated to explain here. – Roee Gavirel Apr 10 '18 at 13:03
0

I would do something like this:

public void sort(Comparator<? super T> comparator) {
    if (dataStart > dataEnd) {
        System.arraycopy(elements, dataStart, elements, dataEnd, capacity-dataStart);
        dataEnd = dataEnd + capacity-dataStart;
        dataStart = 0;
    }
    Arrays.sort(elements, dataStart, dataEnd, comparator);
}
Maurice Perry
  • 9,261
  • 2
  • 12
  • 24