Is it possible to merge iterators in Java? - java

Is it possible to merge iterators in Java? I have two iterators and I want to combine/merge them so that I could iterate though their elements in one go (in same loop) rather than two steps. Is that possible?
Note that the number of elements in the two lists can be different therefore one loop over both lists is not the solution.
Iterator<User> pUsers = userService.getPrimaryUsersInGroup(group.getId());
Iterator<User> sUsers = userService.getSecondaryUsersInGroup(group.getId());
while(pUsers.hasNext()) {
User user = pUsers.next();
.....
}
while(sUsers.hasNext()) {
User user = sUsers.next();
.....
}

Guava (formerly Google Collections) has Iterators.concat.

Also the Apache Commons Collection have several classes for manipulating Iterators, like the IteratorChain, that wraps a number of Iterators.

You could create your own implementation of the Iterator interface which iterates over the iterators:
public class IteratorOfIterators implements Iterator {
private final List<Iterator> iterators;
public IteratorOfIterators(List<Iterator> iterators) {
this.iterators = iterators;
}
public IteratorOfIterators(Iterator... iterators) {
this.iterators = Arrays.asList(iterators);
}
public boolean hasNext() { /* implementation */ }
public Object next() { /* implementation */ }
public void remove() { /* implementation */ }
}
(I've not added generics to the Iterator for brevity.) The implementation is not too hard, but isn't the most trivial, you need to keep track of which Iterator you are currently iterating over, and calling next() you'll need to iterate as far as you can through the iterators until you find a hasNext() that returns true, or you may hit the end of the last iterator.
I'm not aware of any implementation that already exists for this.
Update:
I've up-voted Andrew Duffy's answer - no need to re-invent the wheel. I really need to look into Guava in more depth.
I've added another constructor for a variable number of arguments - almost getting off topic, as how the class is constructed here isn't really of interest, just the concept of how it works.

I haven't written Java code in a while, and this got me curious to whether I've still "got it".
First try:
import java.util.Iterator;
import java.util.Arrays; /* For sample code */
public class IteratorIterator<T> implements Iterator<T> {
private final Iterator<T> is[];
private int current;
public IteratorIterator(Iterator<T>... iterators)
{
is = iterators;
current = 0;
}
public boolean hasNext() {
while ( current < is.length && !is[current].hasNext() )
current++;
return current < is.length;
}
public T next() {
while ( current < is.length && !is[current].hasNext() )
current++;
return is[current].next();
}
public void remove() { /* not implemented */ }
/* Sample use */
public static void main(String... args)
{
Iterator<Integer> a = Arrays.asList(1,2,3,4).iterator();
Iterator<Integer> b = Arrays.asList(10,11,12).iterator();
Iterator<Integer> c = Arrays.asList(99, 98, 97).iterator();
Iterator<Integer> ii = new IteratorIterator<Integer>(a,b,c);
while ( ii.hasNext() )
System.out.println(ii.next());
}
}
You could of course use more Collection classes rather than a pure array + index counter, but this actually feels a bit cleaner than the alternative. Or am I just biased from writing mostly C these days?
Anyway, there you go. The answer to you question is "yes, probably".

public class IteratorJoin<T> implements Iterator<T> {
private final Iterator<T> first, next;
public IteratorJoin(Iterator<T> first, Iterator<T> next) {
this.first = first;
this.next = next;
}
#Override
public boolean hasNext() {
return first.hasNext() || next.hasNext();
}
#Override
public T next() {
if (first.hasNext())
return first.next();
return next.next();
}
}

Starting with Java 8 and later this can be done without external dependencies using Stream API. This also allows concatenation of iterator with other types of streams.
Streams.concat(StreamSupport.stream(<iter1>, false), StreamSupport.stream(<iter2>, false));

move your loop to a method and pass the iterator to method.
void methodX(Iterator x) {
while (x.hasNext()) {
....
}
}

an iterator comes FROM a collection or a set.
why not use the method already available
Collection.addAll(Collection c);
and then create your iterator from the last object.
this way, your iterator will iterate all the contents of both collection.

You can use my version of an extendable iterator. It uses a double-ended queue of iterators which to me makes sense:
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedDeque;
public class ExtendableIterator<T> implements Iterator<T> {
public Deque<Iterator<T>> its = new ConcurrentLinkedDeque<Iterator<T>>();
public ExtendableIterator() {
}
public ExtendableIterator(Iterator<T> it) {
this();
this.extend(it);
}
#Override
public boolean hasNext() {
// this is true since we never hold empty iterators
return !its.isEmpty() && its.peekLast().hasNext();
}
#Override
public T next() {
T next = its.peekFirst().next();
if (!its.peekFirst().hasNext()) {
its.removeFirst();
}
return next;
}
public void extend(Iterator<T> it) {
if (it.hasNext()) {
its.addLast(it);
}
}
}

The Merged Iterator:
import static java.util.Arrays.asList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
public class ConcatIterator<T> implements Iterator<T> {
private final List<Iterable<T>> iterables;
private Iterator<T> current;
#SafeVarargs
public ConcatIterator(final Iterable<T>... iterables) {
this.iterables = new LinkedList<>(asList(iterables));
}
#Override
public boolean hasNext() {
checkNext();
return current != null && current.hasNext();
}
#Override
public T next() {
checkNext();
if (current == null || !current.hasNext()) throw new NoSuchElementException();
return current.next();
}
#Override
public void remove() {
if (current == null) throw new IllegalStateException();
current.remove();
}
private void checkNext() {
while ((current == null || !current.hasNext()) && !iterables.isEmpty()) {
current = iterables.remove(0).iterator();
}
}
}
The concat method to create an Iterable:
#SafeVarargs
public static <T> Iterable<T> concat(final Iterable<T>... iterables) {
return () -> new ConcatIterator<>(iterables);
}
Simple JUnit test:
#Test
public void testConcat() throws Exception {
final Iterable<Integer> it1 = asList(1, 2, 3);
final Iterable<Integer> it2 = asList(4, 5);
int j = 1;
for (final int i : concat(it1, it2)) {
assertEquals(j, i);
j++;
}
}

I would refactor the original design from:
Iterator<User> pUsers = userService.getPrimaryUsersInGroup(group.getId());
Iterator<User> sUsers = userService.getSecondaryUsersInGroup(group.getId());
To something like:
Iterator<User> users = userService.getUsersInGroup(group.getId(), User.PRIMARY, User.SECONDARY, ...);

You can try ConcatIterator from Cactoos:
Iterator<String> names = new ConcatIterator<>(
Arrays.asList("Sarah", "Mary").iterator(),
Arrays.asList("Jeff", "Johnny").iterator(),
);
Also check ConcatIterable, which concatenates Iterables.

In the Apache Commons Collections there is public static <E> Iterator<E> org.apache.commons.collections4.IteratorUtils.chainedIterator(Collection<Iterator<? extends E>> iterators) that says
Gets an iterator that iterates through a collections of Iterators one after another.
which should be what you want.
import java.util.Arrays;
import java.util.Iterator;
import org.apache.commons.collections4.IteratorUtils;
//also works: import org.apache.commons.collections.IteratorUtils;
class Scratch {
public static void main( String[] args ) {
final Iterator<String> combinedIterator = IteratorUtils.chainedIterator(
Arrays.asList( "a", "b", "c" ).iterator(),
Arrays.asList( "1", "2", "3" ).iterator()
);
while( combinedIterator.hasNext() ){
System.out.println( combinedIterator.next() );
}
// "abc123" will have been printed out
}
}

every Iterator object holds own memory location (adress), so you can't simply "merge" them. except if you extend iterator class and write your own implementation there.
If you are dealing with the same number of objects in both iterators an alternative solution would be to process two iterators in one loop like this :
while (iterator1.hasNext() && iterator2.hasNext()) {
// code
}

Related

Interview: Collections Iterator

Hi guys i got this as an interview question and was having trouble with it. I am familiar with generics/collections & iterator but the manner i which the Collection is declared completely threw me.
Heres the question: Contained in the provided workspace is cocI, the start of a class that implements an Iterator that can be used to iterate a Collection of Collections. The Collection of Collections is passed into the constructor of the class. The Iterator should iterate through the contents depth-first.
For example, if the Collection of Collections looks like the following:
[0] – [“A”, “B”, “C”]
[1] – [“D”]
[2] – [“E”, “F”]
The iterator should then return the contents in the following order: “A”, “B”, “C”, “D”, “E”, “F”
Q.Provide implementations for the hasNext() and next() methods in cocI
Thanks
import java.util.Collection;
import java.util.Iterator;
public class cocI implements Iterator<Object> {
private Collection<Collection<Object>> _collOfColl = null;
public cocI(Collection<Collection<Object>> collofColl) {
_collOfColl = collofColl;
}
public boolean hasNext() {
// TODO implement this method
return false;
}
public Object next() {
// TODO implement this method
return null;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
All you need to do is keep track of the current collection's iterator within the collection of collections. The hasnext() method, which is the tricky part, will then do one of two things: return true if the current iterator has more elements, if not search until we find a collection that has elements. If we exhaust all the collections, return false.
public class Cocl implements Iterator<Object> {
private Collection<Collection<Object>> _collOfColl = null;
private final Iterator<Collection<Object>> coClIterator;
private Iterator<Object> currentColIterator;
public Cocl(Collection<Collection<Object>> collofColl) {
_collOfColl = collofColl;
coClIterator = collofColl.iterator();
if (coClIterator.hasNext()) {
currentColIterator = coClIterator.next().iterator();
}
}
public boolean hasNext() {
if (currentColIterator == null) {
return false;
}
if (!currentColIterator.hasNext()) {
while (coClIterator.hasNext()) {
currentColIterator = coClIterator.next().iterator();
if (currentColIterator.hasNext()) {
return true;
}
}
return false;
} else {
return true;
}
}
public Object next() {
if (hasNext()) {
return currentColIterator.next();
}
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
public static void main(String[] args) {
Collection<Object> one = Arrays.asList((Object) "A", (Object) "B", (Object) "C");
Collection<Object> two = Arrays.asList((Object) "D", (Object) "E");
Cocl cocl = new Cocl(Arrays.asList(one, two));
while (cocl.hasNext()) {
Object a = cocl.next();
System.out.println(a);
}
}
}
A couple of introductory remarks:
cocI is an odd class name; it should start with a capital letter.
The interface you are supposed to implement doesn't use generics effectively. You should be able to use a data type more specific than Object.
It is good practice to use the #Override annotation.
The solution involves an iterator for the outer collection and an iterator for the inner collection. When the inner iterator runs out of elements, it needs to be replaced with an iterator for the next collection. However, considering that a collection could be empty, the advancement needs to be done in a loop, which I've put in an advanceCollection() helper.
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class cocI<T> implements Iterator<T> {
private Iterator<Collection<T>> outerIterator;
private Iterator<T> innerIterator;
public cocI(Collection<Collection<T>> collofColl) {
this.outerIterator = collofColl.iterator();
advanceCollection();
}
#Override
public boolean hasNext() {
return this.innerIterator != null && this.innerIterator.hasNext();
}
#Override
public T next() {
if (this.innerIterator == null) {
throw new NoSuchElementException();
}
try {
return this.innerIterator.next();
} finally {
advanceCollection();
}
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
private void advanceCollection() {
while ((this.innerIterator == null || !this.innerIterator.hasNext())
&& this.outerIterator.hasNext()) {
this.innerIterator = this.outerIterator.next().iterator();
}
}
}
There is one slightly tricky piece of code I used:
try {
return this.innerIterator.next();
} finally {
advanceCollection();
}
It is roughly equivalent to:
T result = this.innerIterator.next();
advanceCollection();
return result;

Having trouble making my own iterator for a collections class

I'm getting the error "Iterator cannot be resolved to a type". I'm trying to take the storage class and add the code necessary to implement java's Collections class.
I dont think i'm allowed to import Iterator, i think i need to make my own.
public class storage {
private Object[] data = new Object[256];
// Don't allow access to anything not yet stored
private int nextEmptySlot = 0;
private int i=0;
public Object begin(){
return data[0];
}
public Object end(){
return data[nextEmptySlot];
}
//class Iterator() {
// public Storage data;
//}
public Iterator iterator() {
// returns a class that iterates over the data array
return new Iterator() {
public Object remove(){
for(int j=i+1 ; j<=nextEmptySlot-1 ; j++) {
this.data[j-1] = this.data[j];
}
return (this.data.data[i]);
}
public int hasNext(){
if(this.data.data[i+1] != null) return 1;
else return 0;
}
public Object next(){
i++;
if (hasNext()==1){
return this.data.data[i];
}
else if (hasNext()==0){
throw UnsupportedOperationException();
}
return this;
}
};
}
}
You need to import java.util.Iterator;
This code isn't even wrong; check out the Iterator methods:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/Iterator.html
Your Iterator does not implement the java.util.Iterator interface; using the same name doth not make it one.
Look at your method:
public int hasNext()
The java.util.Iterator hasNext() returns a boolean.
This is utterly wrong.

Allocation free game

My code is basically allocation free, however the GC runs every 30 seconds or so when at 60fps. Checking the app with DDMS for allocation shows there is ALOT of SimpleListIterator being allocated. There is also some stuff being allocated because i use Exchanger.
The SimpleListIterator comes from for each loops for (T obj : objs) {}. I was under the impression that the compilator/translator would optimize those to not use iterators for types that support it (I basically only use ArrayList) but that seems to not be the case.
How can I avoid allocating all these SimpleListIterators? One solution would be to switch to regular for loops for (int i = 0; i < size; ++i) {} but I like for each loops :(
Another way would be to extend ArrayList which returns an Iterator that is only allocated once.
A third way I hacked together is using a static helper function which returns a Collection which is reusing an Iterator. I hacked something like this together but the casting feels very hackish and unsafe. It should be thread safe though as I use ThreadLocal? See below:
public class FastIterator {
private static ThreadLocal<Holder> holders = new ThreadLocal<Holder>();
public static <T> Iterable<T> get(ArrayList<T> list) {
Holder cont = holders.get();
if (cont == null) {
cont = new Holder();
cont.collection = new DummyCollection<T>();
cont.it = new Iterator<T>();
holders.set(cont);
}
Iterator<T> it = (Iterator<T>) cont.it;
DummyCollection<T> collection = (DummyCollection<T>) cont.collection;
it.setList(list);
collection.setIterator(it);
return collection;
}
private FastIterator() {}
private static class Holder {
public DummyCollection<?> collection;
public Iterator<?> it;
}
private static class DummyCollection<T> implements Iterable {
private Iterator<?> it;
#Override
public java.util.Iterator<T> iterator() {
return (java.util.Iterator<T>) it;
}
public void setIterator(Iterator<?> it) {
this.it = it;
}
}
private static class Iterator<T> implements java.util.Iterator<T> {
private ArrayList<T> list;
private int size;
private int i;
#Override
public boolean hasNext() {
return i < size;
}
#Override
public T next() {
return list.get(i++);
}
#Override
public void remove() {
}
public void setList(ArrayList<T> list) {
this.list = list;
size = list.size();
i = 0;
}
private Iterator() {}
}
}
You should not use for each in Android games.
I think this official video talks about that too.
Probably the best approach would be to use a Decorator design. Create a class which takes a collection in the constructor and implements the Iterable interface by calling the wrapped class and reusing the iterator returned.
Two additional approaches for avoiding the allocation of iterators.
First is to use a callback idiom:
public interface Handler<T> {
void handle(T element);
}
public interface Handleable<T> {
void handleAll(Handler<T> handler);
}
public class HandleableList<T> extends ArrayList<T> implements Handleable<T> {
public void handleAll(Handler<T> handler) {
for (int i = 0; i < size(); ++i) {
handler.handle(get(i));
}
}
}
This approach still requires an instance of a Handler to receive the callback, but this can definitely reduce allocations when, for example, you are trying to visit the elements of several lists.
Second approach is to use a cursor idiom:
public interface Cursor<T> {
void reset();
boolean next();
T current();
}
public class CursoredList<T> extends ArrayList<T> implements Cursor<T> {
private int _index = -1;
public void reset() {
_index = -1;
}
public boolean next() {
return ++_index >= size();
}
public T current() {
return get(_index);
}
}
Sure, this is the same as implementing Iterable and Iterator on your subtype of ArrayList, but this clearly shows the cursor location as state on the collection itself.

Java for each, but multiple iterator types?

I have a class Polygon on which I wish to implement two iterators: one to run through all elements (vertices and edges in alternating order) just ONCE, and another to run through them ad infinitum (cyclically).
From a for-each usage standpoint, my guess is that I am only going to be able to have one of the above be the default iterator that can be used with for-each, via implementation of Iterable.iterator(). Is this correct? Or is there a way I could use for-each with both?
Just add two methods returning two different Iterators, one for each case:
public Iterable<String> eachOnce() {
List<String> allResults = new ArrayList<String>();
// fill list
return allResults;
}
public Iterable<String> eachCyclic() {
return new Iterable<String>() {
public Iterator<String> iterator() {
return new Iterator<String>() {
public boolean hasNext() {
return true;
}
public String next() {
// TODO implement
return null;
}
public void remove() {
// do nothing
}
};
}
};
}
This is just an example with a List of Strings, just adapt.
Instead of
for (Polygon p : polygons) { }
just use
for (Polygon p : polygons.eachOnce()) { }
or the cyclic edition
An answer I think is better than those already presented is a method that turns any Iterable into a cyclic one.
public class IterableUtils {
public static class CyclicIterator<T> implements Iterator<T> {
private final Iterable<T> inner;
private Iterator<T> currentIter;
public CyclicIterator(Iterable<T> inner) {
this.inner = inner;
}
public boolean hasNext() {
if (currentIter == null || !currentIter.hasNext()) {
currentIter = inner.iterator();
}
return currentIter.hasNext();
}
public T next() {
if (currentIter == null || !currentIter.hasNext()) {
currentIter = inner.iterator();
}
return currentIter.next();
}
public void remove() {
currentIter.remove();
}
}
public static <T> Iterable<T> cycle(final Iterable<T> i) {
return new Iterable<T>() {
public Iterator<T> iterator() { return new CyclicIterator<T>(i); }
};
}
}
Then you can just implement the single iterator method in the Polygon class and use
for (Element e: polygon) {
...
}
to iterate once and
for (Element e: cycle(polygon)) {
...
}
to iterate endlessly. As a bonus, the cycle modifier can be applied to any iterable.

Is there a fixed sized queue which removes excessive elements?

I need a queue with a fixed size. When I add an element and the queue is full, it should automatically remove the oldest element.
Is there an existing implementation for this in Java?
Actually the LinkedHashMap does exactly what you want. You need to override the removeEldestEntry method.
Example for a queue with max 10 elements:
queue = new LinkedHashMap<Integer, String>()
{
#Override
protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest)
{
return this.size() > 10;
}
};
If the "removeEldestEntry" returns true, the eldest entry is removed from the map.
Yes, Two
From my own duplicate question with this correct answer, I learned of two:
EvictingQueue in Google Guava
CircularFifoQueue in Apache Commons
I made productive use of the Guava EvictingQueue, worked well.
To instantiate an EvictingQueue call the static factory method create and specify your maximum size.
EvictingQueue< Person > people = com.google.common.collect.EvictingQueue.create( 100 ) ; // Set maximum size to 100.
I just implemented a fixed size queue this way:
public class LimitedSizeQueue<K> extends ArrayList<K> {
private int maxSize;
public LimitedSizeQueue(int size){
this.maxSize = size;
}
public boolean add(K k){
boolean r = super.add(k);
if (size() > maxSize){
removeRange(0, size() - maxSize);
}
return r;
}
public K getYoungest() {
return get(size() - 1);
}
public K getOldest() {
return get(0);
}
}
There is no existing implementation in the Java Language and Runtime. All Queues extend AbstractQueue, and its doc clearly states that adding an element to a full queue always ends with an exception. It would be best ( and quite simple ) to wrap a Queue into a class of your own for having the functionality you need.
Once again, because all queues are children of AbstractQueue, simply use that as your internal data type and you should have a flexible implementation running in virtually no time :-)
UPDATE:
As outlined below, there are two open implementations available (this answer is quite old, folks!), see this answer for details.
This is what I did with Queue wrapped with LinkedList, It is fixed sized which I give in here is 2;
public static Queue<String> pageQueue;
pageQueue = new LinkedList<String>(){
private static final long serialVersionUID = -6707803882461262867L;
public boolean add(String object) {
boolean result;
if(this.size() < 2)
result = super.add(object);
else
{
super.removeFirst();
result = super.add(object);
}
return result;
}
};
....
TMarket.pageQueue.add("ScreenOne");
....
TMarket.pageQueue.add("ScreenTwo");
.....
public class CircularQueue<E> extends LinkedList<E> {
private final int capacity;
public CircularQueue(int capacity){
this.capacity = capacity;
}
#Override
public boolean add(E e) {
if(size() >= capacity)
removeFirst();
return super.add(e);
}
}
Usage and test result:
public static void main(String[] args) {
CircularQueue<String> queue = new CircularQueue<>(3);
queue.add("a");
queue.add("b");
queue.add("c");
System.out.println(queue.toString()); //[a, b, c]
String first = queue.pollFirst(); //a
System.out.println(queue.toString()); //[b,c]
queue.add("d");
queue.add("e");
queue.add("f");
System.out.println(queue.toString()); //[d, e, f]
}
I think what you're describing is a circular queue. Here is an example and here is a better one
This class does the job using composition instead of inheritance (other answers here) which removes the possibility of certain side-effects (as covered by Josh Bloch in Essential Java). Trimming of the underlying LinkedList occurs on the methods add,addAll and offer.
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class LimitedQueue<T> implements Queue<T>, Iterable<T> {
private final int limit;
private final LinkedList<T> list = new LinkedList<T>();
public LimitedQueue(int limit) {
this.limit = limit;
}
private boolean trim() {
boolean changed = list.size() > limit;
while (list.size() > limit) {
list.remove();
}
return changed;
}
#Override
public boolean add(T o) {
boolean changed = list.add(o);
boolean trimmed = trim();
return changed || trimmed;
}
#Override
public int size() {
return list.size();
}
#Override
public boolean isEmpty() {
return list.isEmpty();
}
#Override
public boolean contains(Object o) {
return list.contains(o);
}
#Override
public Iterator<T> iterator() {
return list.iterator();
}
#Override
public Object[] toArray() {
return list.toArray();
}
#Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
#Override
public boolean remove(Object o) {
return list.remove(o);
}
#Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
#Override
public boolean addAll(Collection<? extends T> c) {
boolean changed = list.addAll(c);
boolean trimmed = trim();
return changed || trimmed;
}
#Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
#Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
#Override
public void clear() {
list.clear();
}
#Override
public boolean offer(T e) {
boolean changed = list.offer(e);
boolean trimmed = trim();
return changed || trimmed;
}
#Override
public T remove() {
return list.remove();
}
#Override
public T poll() {
return list.poll();
}
#Override
public T element() {
return list.element();
}
#Override
public T peek() {
return list.peek();
}
}
Sounds like an ordinary List where the add method contains an extra snippet which truncates the list if it gets too long.
If that is too simple, then you probably need to edit your problem description.
Also see this SO question, or ArrayBlockingQueue (be careful about blocking, this might be unwanted in your case).
It is not quite clear what requirements you have that led you to ask this question. If you need a fixed size data structure, you might also want to look at different caching policies. However, since you have a queue, my best guess is that you're looking for some type of router functionality. In that case, I would go with a ring buffer: an array that has a first and last index. Whenever an element is added, you just increment the last element index, and when an element is removed, increment the first element index. In both cases, addition is performed modulo the array size, and make sure to increment the other index when needed, that is, when the queue is full or empty.
Also, if it is a router-type application, you might also want to experiment with an algorithm such as Random Early Dropping (RED), which drops elements from the queue randomly even before it gets filled up. In some cases, RED has been found to have better overall performance than the simple method of allowing the queue to fill up before dropping.
Actually you can write your own impl based on LinkedList, it is quite straight forward, just override the add method and do the staff.
I think the best matching answer is from this other question.
Apache commons collections 4 has a CircularFifoQueue which is what you are looking for. Quoting the javadoc:
CircularFifoQueue is a first-in first-out queue with a fixed size that replaces its oldest element if full.
A Simple solution, below is a Queue of "String"
LinkedHashMap<Integer, String> queue;
int queueKeysCounter;
queue.put(queueKeysCounter++, "My String");
queueKeysCounter %= QUEUE_SIZE;
Note that this will not maintain the Order of the items in the Queue, but it will replace the oldest entry.
As it's advised in OOPs that we should prefer Composition over Inheritance
Here my solution keeping that in mind.
package com.choiceview;
import java.util.ArrayDeque;
class Ideone {
public static void main(String[] args) {
LimitedArrayDeque<Integer> q = new LimitedArrayDeque<>(3);
q.add(1);
q.add(2);
q.add(3);
System.out.println(q);
q.add(4);
// First entry ie 1 got pushed out
System.out.println(q);
}
}
class LimitedArrayDeque<T> {
private int maxSize;
private ArrayDeque<T> queue;
private LimitedArrayDeque() {
}
public LimitedArrayDeque(int maxSize) {
this.maxSize = maxSize;
queue = new ArrayDeque<T>(maxSize);
}
public void add(T t) {
if (queue.size() == maxSize) {
queue.removeFirst();
}
queue.add(t);
}
public boolean remove(T t) {
return queue.remove(t);
}
public boolean contains(T t) {
return queue.contains(t);
}
#Override
public String toString() {
return queue.toString();
}
}
Ok, I'll throw out my version too. :-) This is build to be very performant - for when that matters. It's not based on LinkedList - and is thread safe (should be at least). FIFO
static class FixedSizeCircularReference<T> {
T[] entries
FixedSizeCircularReference(int size) {
this.entries = new Object[size] as T[]
this.size = size
}
int cur = 0
int size
synchronized void add(T entry) {
entries[cur++] = entry
if (cur >= size) {
cur = 0
}
}
List<T> asList() {
int c = cur
int s = size
T[] e = entries.collect() as T[]
List<T> list = new ArrayList<>()
int oldest = (c == s - 1) ? 0 : c
for (int i = 0; i < e.length; i++) {
def entry = e[oldest + i < s ? oldest + i : oldest + i - s]
if (entry) list.add(entry)
}
return list
}
}

Categories