It's useful to me to have a data structure in Java that has all the functionality of a List, but has a maximum storage capacity, and drops older data when newer data is added. Conceivably at some point I might want to implement a fixed size Queue which keeps a more general ordering of the data, and drops the old data lowest in that ordering, but that's the for the future.
At the moment I'm implementing it like this:
public class FixedSizeList<T> {
private final int maxSize;
private final LinkedList<T> list = new LinkedList<T>();
public FixedSizeQueue(int maxSize) {
this.maxSize = maxSize < 0 ? 0 : maxSize;
}
public T add(T t) {
list.add(t);
return list.size() > maxSize ? list.remove() : null;
}
// add remaining methods...
}
Is there either (a) an existing data structure that serves my needs, or (b) a better way of implementing this data structure?
I would use array and 2 indexes for head and tail of the list.Make sure that head is always < tail and you're safe.
Here's a List with a size limit, based on Guava's ForwardingList:
A list which forwards all its method
calls to another list. Subclasses
should override one or more methods to
modify the behavior of the backing
list as desired per the decorator
pattern.
Guava has base classes like this for all JDK-5 Collection types. Each of them fulfills the same purpose: making it easy to add value, while delegating all default functionality to the underlying collection.
public class LimitingList<E> extends ForwardingList<E> {
private final class LimitingListIterator extends ForwardingListIterator<E> {
private final ListIterator<E> innerListIterator;
private LimitingListIterator(final ListIterator<E> innerListIterator) {
this.innerListIterator = innerListIterator;
}
/**
* {#inheritDoc}
*/
#Override
public void add(final E element) {
if (inner.size() < maxSize)
innerListIterator.add(element);
else
throw new IndexOutOfBoundsException();
}
#Override
protected ListIterator<E> delegate() {
return innerListIterator;
}
}
public LimitingList(final int maxSize) {
this(new ArrayList<E>(), maxSize);
}
public LimitingList(final List<E> inner, final int maxSize) {
super();
this.inner = inner;
this.maxSize = maxSize;
}
#Override
public boolean addAll(final Collection<? extends E> collection) {
boolean changed = false;
for (final E item : collection) {
final boolean tmpChanged = add(item);
changed = changed || tmpChanged;
if (!tmpChanged)
break;
}
return changed;
}
#Override
public boolean add(final E e) {
if (inner.size() < maxSize)
return super.add(e);
else
return false;
}
#Override
public ListIterator<E> listIterator() {
return new LimitingListIterator(inner.listIterator());
}
#Override
public void add(final int index, final E element) {
throw new UnsupportedOperationException();
}
#Override
public boolean addAll(final int index, final Collection<? extends E> elements) {
throw new UnsupportedOperationException();
}
#Override
public ListIterator<E> listIterator(final int index) {
return new LimitingListIterator(inner.listIterator(index));
}
private final int maxSize;
private final List<E> inner;
#Override
protected List<E> delegate() {
return inner;
}
}
It delegates all real functionality to an underlying list, which is an ArrayList per default (single argument constructor), but you can also supply (two argument constructor)
Unless you want to use an actual array, I don't believe there is a list type data structure you can use.
Personally I would extend one of the existing list classes to get the functionality, and override the add methods. This way you get all the other list operations for free. ie something like the following...
public class FixedSizeArrayList<T> extends ArrayList<T> {
private final int maxSize;
public FixedSizeArrayList(int maxSize) {
super();
this.maxSize = maxSize
}
public boolean add(T t) {
if (size() >= maxSize) {
remove(0);
}
return super.add(t);
}
// implementation of remaining add methods....
}
If you extend the LinkedList class you will have direct access to all it's methods. Instead of having to write stuff like
fixedList.getList().pop()
you could just write
fixedList.pop()
You could then override the methods where you need to add the maxSize criteria.
Related
I have a simple class that wraps an unmodifiable list (it is used as a context for a query):
public class Context<T extends Node> implements Iterable<T> {
private final List<T> m_nodes;
Context(List<T> nodes) {
m_nodes = Collections.unmodifiableList(nodes);
}
#Override
public Iterator<T> iterator() {
return m_nodes.iterator();
}
public int indexOf(T node) {
return m_nodes.indexOf(node);
}
public boolean isEmpty() {
return m_nodes.isEmpty();
}
// context are always sorted by pre value
public boolean containsAll(FDMContext<T> other) {
Iterator<T> oit = other.iterator();
Iterator<T> sit = iterator();
int c = 0;
while( oit.hasNext()) {
T o = oit.next();
while( sit.hasNext()) {
T s = sit.next();
if( s.getPre() == o.getPre()) {
c++;
break;
}
}
}
return c == other.size();
}
public int size() {
return m_nodes.size();
}
public List<T> getNodes() {
return m_nodes;
}
#Override
public String toString() {
return m_nodes.toString();
}
}
The Node class has a Value subclass. I don't think the details of the Node and Value class are important, except that they share a common getPre() method defining a unique node identifier.
If there is a method that expects an Context<Value> parameter but I have an Context<Node> instance as a result of a query where I am certain it only contains Value instances, is it safe to suppress warnings?
e.g.
static Entry makeEntry(Event event, Group head, Group tail, Context<Value> values) {
/* code */
}
...
Context<Node> ctx = query(anotherCtx,somePath); // the result ctx contains only Value objects. The query method returns a Context(Node) object
#SuppressWarnings({ "rawtypes", "unchecked" })
Entry ret = makeEntry( this, headGrp, tailGrp, (Context)tail);
I could create a new context of type Context<Value>, but I'd rather avoid the copy if possible.
I have created two iterators for an array: the first runs the array by rows (iteratorRow) and then by columns and the second, first by columns and then by rows (iteratorColumn).
I have another class, Matrix, in which I must create two methods for performing iteration (iteratorRowColumn and iteratorColumnRow) that return iterators that have created to be accessible to other classes.
The array must implement the Iterable interface and may be configured (using a Boolean) which of the two iterators it shall be refunded by calling iterator () method.
How can I do that? Do I have to do some getters methods? Something like this?
public Iterator iteratorRowColumn () {
return new iteratorRow;
}
I think that the last sentence of assignment explains a problem very well. I am not sure what part of it is unclear so let me explain in detail:
The array must implement the Iterable interface
public class Matrix<T> implements Iterable<T>
may be configured (using a Boolean)
public Matrix(boolean defaultRowColumnIterator) {
this.defaultRowColumnIterator = defaultRowColumnIterator;
}
which of the two iterators it shall be returning by calling iterator() method
#Override
public Iterator<T> iterator() {
return defaultRowColumnIterator ? iteratorRowColumn() : iteratorColumnRow();
}
Here is a compilable example:
public class Matrix<T> implements Iterable<T> {
T[][] array;
boolean defaultRowColumnIterator;
public Matrix(boolean defaultRowColumnIterator) {
this.defaultRowColumnIterator = defaultRowColumnIterator;
}
// other methods and constructors
public Iterator<T> iteratorRowColumn() {
return null; // your current implementation
}
public Iterator<T> iteratorColumnRow() {
return null; // your current implementation
}
#Override
public Iterator<T> iterator() {
return defaultRowColumnIterator ? iteratorRowColumn() : iteratorColumnRow();
}
}
Something like this:
public class Proba {
Integer[][] array = new Integer[10][10];
public class MyIter implements Iterator<Integer> {
private Integer[] integers;
private int index = 0;;
public MyIter(Integer[] integers) {
this.integers = integers;
}
#Override
public boolean hasNext() {
return index < integers.length -1 ;
}
#Override
public Integer next() {
return integers[index];
}
#Override
public void remove() {
//TODO: remove
}
}
public static void main(String[] args) {
Iterator<Integer> iter = new Proba().getIterator(1);
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
public Iterator<Integer> getIterator(int row) {
return new MyIter(array[row]);
}
}
This is a classic implementation of an immutable linked list:
public abstract class List<A> implements Iterable<A> {
private static final List NIL = new Nil();
public abstract A head();
public abstract List<A> tail();
public List<A> cons(A a) { return new Cons<>(a, this); }
public static <A> List<A> nil() { return NIL; }
#Override
public Iterator<A> iterator() {
return new Iterator<A>() {
private List<A> list = List.this;
#Override
public boolean hasNext() {
return list != NIL;
}
#Override
public A next() {
A n = list.head();
list = list.tail();
return n;
}
};
}
public Stream<A> stream() {
return StreamSupport.stream(spliterator(), false);
}
public Stream<A> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
class Nil extends List {
#Override public Object head() { throw new NoSuchElementException(); }
#Override public List tail() { throw new NoSuchElementException(); }
}
class Cons<A> extends List<A> {
private final A head;
private final List<A> tail;
Cons(A head, List<A> tail) {
this.head = head;
this.tail = tail;
}
#Override public A head() { return head; }
#Override public List<A> tail() { return tail; }
}
The default implementation of spliterator() does not support efficient parallelizing:
List<Integer> list = List.<Integer> nil().cons(3).cons(2).cons(1);
list.parallelStream().forEach(i -> {
System.out.println(i);
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
});
This will print 1, 2, 3 sequentially.
How to implement spliterator() to support efficient parallelizing?
The spliterators which cannot report even the estimated size (which is default implementation for Iterable) are poorly split by parallel pipeline. You can fix this issue if you track the size of the List. In your case it's not very hard to track the exact size:
public abstract class List<A> implements Iterable<A> {
...
public abstract long size();
#Override
public Spliterator<A> spliterator() {
return Spliterators.spliterator(iterator(), size(), Spliterator.ORDERED);
}
}
class Nil extends List {
...
public long size() {
return 0;
}
}
class Cons<A> extends List<A> {
...
private final long size;
Cons(A head, List<A> tail) {
this.head = head;
this.tail = tail;
this.size = tail.size()+1;
}
...
#Override
public long size() {
return size;
}
}
After that parallelization would work better. Note that it's still poor man parallelization, because you cannot quickly jump to the middle of the list, but in many cases it will provide a reasonable speed-up.
Also note that it's better to explicitly specify the Spliterator.ORDERED characteristic. Otherwise the order may be ignored in parallel stream operations even if it's explicitly requested (for example, by forEachOrdered() terminal operation).
You might use some algorithm with interleaving - e.g., counting the elements and using remainder after integer division. That could split the elements for parallel iteration.
You could also iterate once before the iterator is even constructed, to split the list into intervals, but that would beat the purpose of stream - e.g. if you use it for anyMatch, it will slow you a lot.
There is no really efficient way to split a linked list (in less than linear time), unless you create your own implementation of linked list that has some additional information.
Edit: Oh wait - you only implement Iterable. That is quite limiting, you have to come up with an algorithm that only has one pass. That means, the splitting itself won't be parallel at all, so you might as well enforce your parallelism elsewhere in the process.
For a homework assignment, I need to implement my own PriorityQueue and PriorityQueueSort. I used generics to get it working without the sort function, but now I'm stuck here..
public static void PriorityQueueSort(Iterable<?> list,
PriorityQueue<?,?> pq) {
if (!pq.isEmpty()) {
throw new IllegalArgumentException("Non-Empty PriorityQueue");
}
for (Object obj : list) {
}
}
I need to pass in a list and an empty PriorityQueue, so my best guess at how to do this is just above. How should I attack this so that I can iterate through the list with unknown type, and add each element in that list with the proper type into the priority queue?
Edit:
Here are a few more details since it was determined that I didn't include enough information.
I have a custom PriorityQueue class, and a custom Entry class that holds a key of type K, and a value of type V.
I need to be able to take any iterable list with any type T and iterate through it, taking each item and add it to an initially empty PriorityQueue as a key with null value. I then need to continuously call removeMin() on my PriorityQueue and add it in order back into the same list object.
public class PriorityQueue<K extends Comparable<? super K>,V> {
private Entry<K,V> _head;
private Entry<K,V> _tail;
private int _size;
public PriorityQueue() {
this._head = null;
this._tail = null;
this._size = 0;
}
public int size() {
return _size;
}
public boolean isEmpty() {
return (size() == 0);
}
public Entry<K,V> min() {
if (_head == null) {
return null;
}
Entry<K,V> current = _head;
Entry<K,V> min = _head;;
while (current != null) {
if (current.compareTo(min) < 0) {
min = current;
}
current = current.getNext();
}
return min;
}
public Entry<K,V> insert(K k, V x) {
Entry<K,V> temp = new Entry<K,V>(k,x);
if (_tail == null) {
_tail = temp;
_head = temp;
}
else {
_tail.setNext(temp);
temp.setPrev(_tail);
_tail = temp;
}
return temp;
}
public Entry<K,V> removeMin() {
Entry<K,V> smallest = min();
smallest.getPrev().setNext(smallest.getNext());
smallest.getNext().setPrev(smallest.getPrev());
return smallest;
}
public String toString() {
return null;
}
public static <K> void PriorityQueueSort(Iterable<? extends K> list,
PriorityQueue<? super K, ?> queue) {
for (K item : list) {
queue.insert(item, null);
}
list.clear();
}
public static void main(String[] args) {
PriorityQueue<Integer, Integer> pq =
new PriorityQueue<Integer, Integer>();
pq.insert(4, 2);
pq.insert(5, 1);
System.out.println(pq.min().toString());
}
}
What you've got at the moment doesn't make sense in terms of the method signature - it would let you pass in a List<Button> and a PriorityQueue<String> for example.
I suspect you actually want something like:
public static <T> void prioritySortQueue(Iterable<? extends T> iterable,
PriorityQueue<? super T> queue) {
for (T item : iterable) {
queue.add(item);
}
}
Note that the variance here just gives more flexibility - you could have a List<Circle> but a PriorityQueue<Shape> for example, and it's still type-safe.
EDIT: Now that we have more details, I think you want something like this:
public static <K> void prioritySortQueue(Iterable<? extends K> iterable,
PriorityQueue<? super K, ?> queue) {
for (T item : iterable) {
queue.put(item, null);
}
}
(Assuming you have a put method. We still don't know what your PriorityQueue class looks like.)
You need to make the method generic so that you can refer to the type:
public static <T> void PriorityQueueSort(Iterable<T> list,
PriorityQueue<?,T> pq) {
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.
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);
}
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.
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.
Extend the ArrayList class and implement the get(Integer) method the way you like. I think this is the 'best practice'.