View Javadoc
1   package com.github.davidmoten.util;
2   
3   import java.util.Collection;
4   import java.util.Iterator;
5   import java.util.NoSuchElementException;
6   import java.util.Queue;
7   
8   /**
9    * Non-threadsafe implementation of a Ring Buffer. Does not accept nulls.
10   * 
11   * @param <T>
12   */
13  // @NotThreadSafe
14  public class RingBuffer<T> implements Queue<T> {
15  
16      private final T[] list;
17      private int start;
18      private int finish;
19  
20      @SuppressWarnings("unchecked")
21      private RingBuffer(int size) {
22          list = (T[]) new Object[size + 1];
23      }
24  
25      public static <T> RingBuffer<T> create(int size) {
26          return new RingBuffer<T>(size);
27      }
28  
29      @Override
30      public void clear() {
31          finish = start;
32      }
33  
34      @Override
35      public Iterator<T> iterator() {
36          final int _start = start;
37          final int _finish = finish;
38          return new Iterator<T>() {
39              int i = _start;
40  
41              @Override
42              public boolean hasNext() {
43                  return i != _finish;
44              }
45  
46              @Override
47              public T next() {
48                  T value = list[i];
49                  i = (i + 1) % list.length;
50                  return value;
51              }
52          };
53      }
54  
55      @Override
56      public T peek() {
57          if (start == finish)
58              return null;
59          else
60              return list[start];
61      }
62  
63      public boolean isEmpty() {
64          return start == finish;
65      }
66  
67      public int size() {
68          if (start <= finish)
69              return finish - start;
70          else
71              return finish - start + list.length;
72      }
73  
74      public int maxSize() {
75          return list.length - 1;
76      }
77  
78      @Override
79      public boolean contains(Object o) {
80          return notImplemented();
81      }
82  
83      @Override
84      public Object[] toArray() {
85          return notImplemented();
86      }
87  
88      @Override
89      public <S> S[] toArray(S[] a) {
90          return notImplemented();
91      }
92  
93      @Override
94      public boolean remove(Object o) {
95          return notImplemented();
96      }
97  
98      @Override
99      public boolean containsAll(Collection<?> c) {
100         return notImplemented();
101     }
102 
103     private static <T> T notImplemented() {
104         throw new RuntimeException("Not implemented");
105     }
106 
107     @Override
108     public boolean addAll(Collection<? extends T> c) {
109         for (T t : c)
110             add(t);
111         return true;
112     }
113 
114     @Override
115     public boolean removeAll(Collection<?> c) {
116         return notImplemented();
117     }
118 
119     @Override
120     public boolean retainAll(Collection<?> c) {
121         return notImplemented();
122     }
123 
124     @Override
125     public boolean add(T t) {
126         if (offer(t))
127             return true;
128         else
129             throw new IllegalStateException("Cannot add to queue because is full");
130     }
131 
132     @Override
133     public boolean offer(T t) {
134         if (t == null)
135             throw new NullPointerException();
136         int currentFinish = finish;
137         finish = (finish + 1) % list.length;
138         if (finish == start) {
139             return false;
140         } else {
141             list[currentFinish] = t;
142             return true;
143         }
144     }
145 
146     @Override
147     public T remove() {
148         T t = poll();
149         if (t == null)
150             throw new NoSuchElementException();
151         else
152             return t;
153     }
154 
155     @Override
156     public T poll() {
157         if (start == finish) {
158             return null;
159         } else {
160             T value = list[start];
161             // don't hold a reference to a popped value
162             list[start] = null;
163             start = (start + 1) % list.length;
164             return value;
165         }
166     }
167 
168     @Override
169     public T element() {
170         return notImplemented();
171     }
172     
173     @Override
174     public String toString() {
175         StringBuilder s = new StringBuilder();
176         s.append("RingBuffer[");
177         boolean first = true;
178         for (T value: this) {
179             if (!first) {
180                 s.append(", ");
181             } else {
182                 first = false;
183             }
184             s.append(String.valueOf(value));
185         }
186         s.append("]");
187         return s.toString();
188     }
189 }