Create a buffer of 3 elements.

`UnboundedFifoBuffer buf = new UnboundedFifoBuffer(3);`

Internally the implementation creates an extra element. Head and tail indices are equal to 0 as we have not added or removed any elements. As we add elements, tail index increases. When size of buffer equals the allocated buffer length, array is expanded so that size=size*2+1.

### Remove

When we remove element, we get an extra vacant element. The head index points to 1. As we remove more elements, the head index increases further. When we add new elements, it will re-use the vacant elements.

In the above example, the tail index is pointing to the last element of the array. Since we have vacant elements due to the remove operation, instead of resizing the array, it will re-use the vacant elements. The tail index will point to 0 so that the next add will fill the 0 index element. As we add new elements, the tail index will increase. Since tail index is < head index, the size would be buffer length – head + tail.

### Iterator

Iterator returns elements in the incremental order starting from head, till it reaches tail. If tail < head, element order will be from head to array’s last element and then 0 to tail index. In the example, iterator will return 5, 6, 7 (last element of array), 8 (index=0), 9, 10(index=tail)

### Remove during iteration

If it is the first element, it can be removed quickly else we will have to left shift elements. In the below example, iterator returns first element 5. We do next() to get 6, and then call remove.

### Re-sizing

Since size equals buffer length, adding a new element will expand the array. The elements will be re-positioned in the new array in the order from head->tail.

### Unit test

```
public void testBuffLen() {
//Create a buffer of 3 elements
UnboundedFifoBuffer buf = new UnboundedFifoBuffer(3);
//Internally the implementation creates an extra element, not sure why?
assertEquals(4, buf.buffer.length);
//Head and tail indexes are equal to 0 as we have not added or removed any elements
assertEquals(0, buf.tail);

//As we add elements, tail index is incremented

assertEquals(1, buf.tail);
assertEquals(1, buf.size());

assertEquals(2, buf.size());

assertEquals(3, buf.size());
assertEquals(4, buf.buffer.length);

//When size of buffer equals the allocated buffer length, array is expanded so that size=size*2+1
assertEquals(4, buf.size());
assertEquals(7, buf.buffer.length);

assertEquals(6, buf.size());
assertEquals(7, buf.buffer.length);

//When we remove element, we get an extra vacant element.
buf.remove();

//Since the first element is removed, head index is incremented to 1
//When we add new elements, instead of re-sizing, it will re-use the vacant elements
assertEquals(5, buf.size());
assertEquals(6, buf.tail);

//As we remove more elements, the head index is incremented further
buf.remove();
buf.remove();
buf.remove();

assertEquals(2, buf.size());
assertEquals(6, buf.tail);

//Tail index is pointing to the end element in buffer. Since we have vacant elements due to the remove operation,
//instead of resizing the array, it will re-use the vacant elements.

//Tail index now points to 0 to reuse the vacant elements
assertEquals(3, buf.size());
assertEquals(0, buf.tail);
assertEquals(7, buf.buffer.length);

//Get method returns element pointing by the head index
assertEquals(5, buf.get());
assertEquals(5, buf.get());

//Add new elements, tail index is incremented

//Tail index is < head index so size = buffer length - head + tail
assertEquals(2, buf.tail);
assertEquals(5, buf.size());
assertEquals(7, buf.buffer.length);