I need some container to keep elements so, if I'll try to get the size()+i element, i'll get element number i. Or with iterator, which starts from the beginning of container after it tries to get the last element? What are the best practicies in both cases? I mean performance and easy useability.
-
1I think that's called a "ring buffer", or a "circular buffer". Not sure about Java, C++ has one in Boost... – Kerrek SB Aug 26 '11 at 20:22
-
Are you sure it's a good idea to have such a data structure? What do you need it for? – toto2 Aug 26 '11 at 21:25
-
I have a DodgerAI class, which handles AI for some hero in game. It has a field - index of hero and field, representing game logic. There are many situations in AI (method in DodgerAI), when all heros, except hero, controlled by AI, must be analyzed. Thats why I want to use some kind of "ring". – Deepscorn Aug 27 '11 at 17:20
4 Answers
You could create a simple subclass of ArrayList<T>
and override the get(int n)
method as follows:
public T get(int n)
{
return super.get(n % this.size());
}
As to the iterator, you will need to implement your own, which shouldn't be all that hard.
EDIT:
Assuming your new class is called RingList, here's a sample RingIterator (untested):
public class RingIterator<T> implements Iterator<T>
{
private int cur = 0;
private RingList<T> coll = null;
protected RingIterator(RingList<T> coll) { this.coll = coll; }
public boolean hasNext() { return size() > 0; }
public T next()
{
if (!hasNext())
throw new NoSuchElementException();
int i=cur++;
cur=cur%size();
return coll.get(i);
}
public void remove() { throw new UnsupportedOperationException(); }
}
You would then override the iterator()
method in RingList<T>
as
public Iterator<T> iterator()
{
return new RingIterator(this);
}

- 85,615
- 20
- 155
- 190
-
Shouldn't all methods (`remove` etc) use the same indexing not just `get`? Mini-bug: When `cur` wraps.. – dacwe Aug 26 '11 at 20:50
-
@dacwe: Of course. I could say "left as an exercise for the reader" :-) – Jim Garrison Aug 26 '11 at 20:51
-
1:-) Great, now it's just the case with an empty list, but that we leave ;-) – dacwe Aug 26 '11 at 20:56
-
It seems the empty list state has been implemented as well in the code above, so it wasn't left :). – Maarten Bodewes Aug 12 '12 at 18:13
For the first part, just ask for n % list.size()
perhaps?
For the iterator part, create a class that wraps an iterator, and when next() returns null, just have it reset the iterator.

- 17,845
- 8
- 50
- 74
Thanks everyone, thats what I've created:
public class RingIterator<E> {
private List<E> _lst;
private ListIterator<E> _lstIter;
public RingIterator(ListIterator<E> iter, List<E> lst) {
super();
_lstIter = iter;
_lst = lst;
}
public E next() {
if(!_lstIter.hasNext())
_lstIter = _lst.listIterator();
return _lstIter.next();
}
public E previous() {
if(!_lstIter.hasPrevious())
_lstIter = _lst.listIterator(_lst.size());
return _lstIter.previous();
}
}
Then get method:
/*
* Returns ring iterator,
* use it with 'ParentClass' type.
*/
public RingIterator<SubClass> getRingIter(int i) {
return new RingIterator(_subs.listIterator(i),_subs);
}
And I use it:
RingIterator<SubClass> ri = _logic.getRingIter(1);
ParentClass ai = ri.next();
I wanted to make only type ParentClass (not SubClass) available via getRingIter, but I don't see a way to do it with no creation of List - convertion of List.

- 822
- 10
- 22
Extend the ArrayList class and implement the get(Integer)
method the way you like. I think this is the 'best practice'.

- 1,672
- 2
- 18
- 38