
org.numenta.nupic.util.Deque Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of htm.java Show documentation
Show all versions of htm.java Show documentation
The Java version of Numenta's HTM technology
/* ---------------------------------------------------------------------
* Numenta Platform for Intelligent Computing (NuPIC)
* Copyright (C) 2014, Numenta, Inc. Unless you have an agreement
* with Numenta, Inc., for a separate license for this software code, the
* following terms and conditions apply:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* http://numenta.org/licenses/
* ---------------------------------------------------------------------
*/
package org.numenta.nupic.util;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingDeque;
/**
* Double ended queue implementation which has a restricted capacity.
* Operations may be conducted on both ends and when capacity is reached,
* the next addition to either end will result in a removal on the opposite
* end, thus always maintaining a size <= initial size.
*
* This behavior differs from the {@link LinkedBlockingDeque} implementation
* of the Java Collections Framework, and is the reason for the development of this
* "alternative" - by allowing constant mutation of this list without an exception
* being thrown and forcing the client to handle capacity management logic.
*
* @author David Ray
*
* @param
*/
public class Deque implements Iterable {
/** Backing array list */
private LinkedBlockingDeque backingList = new LinkedBlockingDeque();
/** Originating size of this {@code Deque} */
private int capacity;
/** The internal size monitor */
private int currentSize;
/**
* Constructs a new {@code Deque} with the specified capacity.
* @param capacity
*/
public Deque(int capacity) {
this.capacity = capacity;
}
/**
* Appends the specified item to the end of this {@code Deque}
*
* @param t the object of type <T> to add
* @return flag indicating whether capacity had been reached
* prior to this call.
*/
public boolean append(E t) {
boolean ret = currentSize == capacity;
if(ret) {
backingList.removeFirst();
backingList.addLast(t);
}else{
backingList.addLast(t);
currentSize++;
}
return ret;
}
/**
* Inserts the specified item at the head of this {@code Deque}
*
* @param t the object of type <T> to add
* @return flag indicating whether capacity had been reached
* prior to this call.
*/
public boolean insert(E t) {
boolean ret = currentSize == capacity;
if(ret) {
backingList.removeLast();
backingList.addFirst(t);
}else{
backingList.addFirst(t);
currentSize++;
}
return ret;
}
/**
* Appends the specified item to the end of this {@code Deque},
* and if this deque was at capacity prior to this call, the object
* residing at the head of this queue is returned, otherwise null
* is returned
*
* @param t the object of type <T> to add
* @return the object residing at the head of this queue is
* returned if previously at capacity, otherwise null
* is returned
*/
public E pushLast(E t) {
E retVal = null;
boolean ret = currentSize == capacity;
if(ret) {
retVal = backingList.removeFirst();
backingList.addLast(t);
}else{
backingList.addLast(t);
currentSize++;
}
return retVal;
}
/**
* Inserts the specified item at the head of this {@code Deque},
* and if this deque was at capacity prior to this call, the object
* residing at the tail of this queue is returned, otherwise null
* is returned
*
* @param t the object of type <T> to add
* @return the object residing at the tail of this queue is
* returned if previously at capacity, otherwise null
* is returned
*/
public E pushFirst(E t) {
E retVal = null;
boolean ret = currentSize == capacity;
if(ret) {
retVal = backingList.removeLast();
backingList.addFirst(t);
}else{
backingList.addFirst(t);
currentSize++;
}
return retVal;
}
/**
* Clears this {@code Deque} of all contents
*/
public void clear() {
backingList.clear();
currentSize = 0;
}
/**
* Returns the item at the head of this {@code Deque} or null
* if it is empty. This call does not block if empty.
*
* @return item at the head of this {@code Deque} or null
* if it is empty.
*/
public E takeFirst() {
if(currentSize == 0) return null;
E val = null;
try {
val = backingList.takeFirst();
currentSize--;
}catch(Exception e) { e.printStackTrace(); }
return val;
}
/**
* Returns the item at the tail of this {@code Deque} or null
* if it is empty. This call does not block if empty.
*
* @return item at the tail of this {@code Deque} or null
* if it is empty.
*/
public E takeLast() {
if(currentSize == 0) return null;
E val = null;
try {
val = backingList.takeLast();
currentSize--;
}catch(Exception e) { e.printStackTrace(); }
return val;
}
/**
* Returns the item at the head of this {@code Deque}, blocking
* until an item is available.
*
* @return item at the tail of this {@code Deque}
*/
public E head() {
E val = null;
try {
val = backingList.takeFirst();
currentSize--;
}catch(Exception e) { e.printStackTrace(); }
return val;
}
/**
* Returns the item at the tail of this {@code Deque} or null
* if it is empty. This call does not block if empty.
*
* @return item at the tail of this {@code Deque} or null
* if it is empty.
*/
public E tail() {
E val = null;
try {
val = backingList.takeLast();
currentSize--;
}catch(Exception e) { e.printStackTrace(); }
return val;
}
/**
* Returns an array containing all of the elements in this deque,
* in proper sequence; the runtime type of the returned array is
* that of the specified array.
*
* @param a array indicating return type
* @return the contents of this {@code Deque} in an array of
* type <T>
*/
public T[] toArray(T[] a) {
return backingList.toArray(a);
}
/**
* Returns the number of elements in this {@code Deque}
* @return
*/
public int size() {
return currentSize;
}
/**
* Returns the capacity this {@code Deque} was last configured with
* @return
*/
public int capacity() {
return capacity;
}
/**
* Resizes the capacity of this {@code Deque} to the capacity
* specified.
*
* @param newCapacity
* @throws IllegalArgumentException if the specified new capacity is less than
* the previous capacity
*/
public void resize(int newCapacity) {
if(capacity == newCapacity) return;
if(capacity > newCapacity) {
throw new IllegalArgumentException("Cannot resize to less than " +
"the original capacity: " + capacity + " > " + newCapacity);
}
this.capacity = newCapacity;
}
/**
* Retrieves, but does not remove, the first element of this deque, or
* returns null if this deque is empty.
*
* @return
*/
public E peekFirst() {
return backingList.peekFirst();
}
/**
* Retrieves, but does not remove, the last element of this deque, or
* returns null if this deque is empty.
*
* @return
*/
public E peekLast() {
return backingList.peekLast();
}
/**
* Returns an {@link Iterator} over the contents of this {@code Deque}
* @return
*/
public Iterator iterator() {
return backingList.iterator();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((backingList == null) ? 0 : backingList.hashCode());
result = prime * result + capacity;
result = prime * result + currentSize;
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Deque other = (Deque) obj;
if (capacity != other.capacity)
return false;
if (currentSize != other.currentSize)
return false;
if (backingList == null) {
if (other.backingList != null)
return false;
} else if (!deepEquals(other))
return false;
return true;
}
private boolean deepEquals(Deque other) {
Iterator otherIt = other.iterator();
for(Iterator it = iterator();it.hasNext();) {
if(!otherIt.hasNext() || !it.next().equals(otherIt.next())) {
return false;
}
}
return true;
}
/**
* {@inheritDoc}
*/
public String toString() {
return backingList.toString() + " capacity: " + capacity;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy