All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.akurilov.commons.collection.CircularArray Maven / Gradle / Ivy

package com.github.akurilov.commons.collection;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import static java.util.Arrays.binarySearch;

/**
 * Created on 05.05.16.
 */
public class CircularArray
implements Iterable {

	private final int length;
	private final T[] array;
	private final Comparator arrayComparator;
	// an array index on which the next item will be recorded
	private int size = 0;
	private int pointer = 0;

	@SuppressWarnings("unchecked")
	public CircularArray(final int length, final Comparator arrayComparator) {
		this.length = length;
		array = (T[]) new Object[length];
		this.arrayComparator = arrayComparator;
	}

	public void addItem(final T item) {
		if(pointer == length) {
			pointer = 0;
		}
		array[pointer++] = item;
		if(size < length) {
			size++;
		}
	}

	public int searchItem(final T item) {
		int index = binarySearch(array, pointer, size, item, arrayComparator);
		if(index < 0) {
			index = binarySearch(array, 0, pointer, item, arrayComparator);
		}
		return index;
	}

	public List getLastItems(final T item) {
		final List lastItems = new ArrayList<>(size);
		final int searchedItemIndex = searchItem(item);
		final Iterator iterator = new LastItemsIterator(searchedItemIndex);
		while (iterator.hasNext()) {
			lastItems.add(iterator.next());
		}
		return lastItems;
	}

	public int size() {
		return size;
	}

	public Iterator plainIterator() {
		return new PlainIterator();
	}

	@Override
	public Iterator iterator() {
		return new LastItemsIterator();
	}

	public Iterator iterator(final int startIndex) {
		return new LastItemsIterator(startIndex);
	}

	private class PlainIterator implements Iterator {

		private int pointer = 0;

		@Override
		public boolean hasNext() {
			return pointer < CircularArray.this.size;
		}

		@Override
		public T next() {
			return CircularArray.this.array[pointer++];
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	private class LastItemsIterator implements Iterator {

		private int pointer;
		private boolean circularity = false;
		private int finishIndex;

		public LastItemsIterator() {
			this(-1);
		}

		public LastItemsIterator(final int startIndex) {
			final int arrayPrePointerIndex = CircularArray.this.pointer - 1;
			if(size < length) {
				if(startIndex < 0) {
					this.pointer = -1;
				} else {
					this.pointer = startIndex;
				}
				finishIndex = size - 1;
				return;
			}
			if(startIndex < 0) {
				this.pointer = arrayPrePointerIndex;
			} else {
				this.pointer = startIndex;
			}
			finishIndex = arrayPrePointerIndex;
			if(this.pointer >= finishIndex && startIndex != arrayPrePointerIndex) {
				circularity = true;
			}
		}

		@Override
		public boolean hasNext() {
			if(circularity) {
				if(pointer == (CircularArray.this.length - 1)) {
					pointer = -1;
					circularity = false;
				}
				return true;
			} else {
				return pointer < finishIndex;
			}
		}

		@Override
		public T next() {
			return CircularArray.this.array[++pointer];
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}
	
	private static final ThreadLocal
		STRING_BULDER = ThreadLocal.withInitial(StringBuilder::new);
	@Override
	public String toString() {
		final StringBuilder valuesBuilder = STRING_BULDER.get();
		valuesBuilder.setLength(0);
		valuesBuilder.append('[');
		if(size > 0) {
			for(int i = 0; i < size; i ++) {
				valuesBuilder.append(' ').append(this.array[i].toString()).append(", ");
			}
			valuesBuilder.delete(valuesBuilder.length() - 2, valuesBuilder.length() - 1);
		}
		valuesBuilder.append(']');
		return valuesBuilder.toString();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy