Currently I'm developing a merge between two sorted collections of elements of type T (the type is not important as long you provide a means to compare the Type, for example, in Java, A Comparator<T> will do the work).
What I don't want is to necessarily merge both data structures involved in the merge process (I don't want to get an entire new structure holding both elements merged). What I want is to have some kind of observer of the merge process in order to define what to do with each merged element in another class. For example, a would like to have something like this:
merger.merge(leftCollection,rightCollection,theComparator,theObserver).
Where the observer is a object watching the merge algorithm and gets notified of the actions, i mean :
interface MergeObserver<T> {
/**
* Triggered when the merge algorithm decides to merge only the left entry.
* This case correspond to the case when there is no equivalent entry on the right collection.
*/
public void mergeLeft(T entry);
/**
* Triggered when the merge algorithm decides to merge both entries.
* This case correspond to the case when there exists the same entry on both collections.
*/
public void mergeBoth(T left, T right);
/**
* Triggered when the merge algorithm decides to merge only the right entry.
* This case correspond to the case when there is no equivalent entry on the left collection.
*/
public void mergeRight(T entry);
}
I have already make my implementation for sorted collections, but... I would like to share this feeling, and here comes the question, about if someone has thought of this before, specially in Guava Libraries, and what are the proper terminology employed.
The two most commonly used patterns for separating the traversal of a data structure and the processing of the data are the visitor pattern and the iterator pattern. Both of those patterns can be applied not only to real data structures that are present in memory but also to "virtual" data structures (which is probably not the proper term). e.g. the method List.subList in the Java API creates a view of a part of the list. So the List object returned by it is just a reference to part of another lists data. Of course you can also combine data structures. You could for example have a method that takes as arguments two iterators and returns a new iterator that merges the two without using any additional memory because that merged list is not actually present in RAM.
If you used Scala instead of Java you would have lots of methods available that can transform iterators in many different ways to achieve effects like this.
import java.util.function.Predicate;
import java.util.function.BiPredicate;
import java.util.function.Supplier;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.NoSuchElementException;
interface MyIterator<T> extends Iterator<T> {
class Peekable<T> {
private final MyIterator<T> iter;
private T next = null;
private boolean isNextBuffered = false;
private boolean atEnd = false;
private Peekable(MyIterator<T> iter) {
this.iter = iter;
}
private void advance() {
if(atEnd) throw new NoSuchElementException();
if(iter.hasNext()) {
next = iter.next();
isNextBuffered = true;
} else {
atEnd = true;
}
}
private boolean hasNext() {
if(atEnd) return false;
if(!isNextBuffered) advance();
return !atEnd;
}
private T next() {
T next = peek();
advance();
return next;
}
private T peek() {
if(hasNext()) return next;
throw new NoSuchElementException();
}
}
static <T> MyIterator<T> of(BooleanSupplier hasNext, Supplier<T> next) {
return new MyIterator<T>() {
public boolean hasNext() {
return hasNext.getAsBoolean();
}
public T next() {
return next.get();
}
};
}
static <T> MyIterator<T> of(Iterator<T> iter) {
return of(iter::hasNext, iter::next);
}
static MyIterator<Integer> range(int start, int end) {
int[] value = {start};
return of(() -> value[0] < end, () -> value[0]++);
}
default <R> MyIterator<R> map(Function<? super T,? extends R> mapper) {
return of(this::hasNext, () -> mapper.apply(this.next()));
}
default MyIterator<T> filter(Predicate<? super T> predicate) {
Peekable<T> iter = new Peekable<T>(this);
return new MyIterator<T>() {
public boolean hasNext() {
while(iter.hasNext() && !predicate.test(iter.peek())) iter.advance();
return iter.hasNext();
}
public T next() {
hasNext();
return iter.next();
}
};
}
default MyIterator<T> merge(MyIterator<T> other, BiPredicate<? super T,? super T> smallerEqual) {
Peekable<T> iter1 = new Peekable<T>(this);
Peekable<T> iter2 = new Peekable<T>(other);
return of(() -> iter1.hasNext() || iter2.hasNext(),
() -> {
if(!iter1.hasNext()) return iter2.next();
else if(!iter2.hasNext()) return iter1.next();
else {
T elem1 = iter1.peek();
T elem2 = iter2.peek();
return smallerEqual.test(elem1, elem2) ? iter1.next() : iter2.next();
}
});
}
}
interface MyIterable<T> extends Iterable<T> {
default Iterator<T> iterator() {
return myIterator();
}
MyIterator<T> myIterator();
static <T> MyIterable<T> of(Supplier<MyIterator<T>> myIterator) {
return new MyIterable<T>() {
public MyIterator<T> myIterator() {
return myIterator.get();
}
};
}
static <T> MyIterable<T> of(Iterable<T> iterable) {
return of(() -> MyIterator.of(iterable.iterator()));
}
static MyIterable<Integer> range(int start, int end) {
return of(() -> MyIterator.range(start, end));
}
default <R> MyIterable<R> map(Function<? super T,? extends R> mapper) {
return of(() -> this.myIterator().map(mapper));
}
default MyIterable<T> filter(Predicate<? super T> predicate) {
return of(() -> this.myIterator().filter(predicate));
}
default MyIterable<T> merge(MyIterable<T> other, BiPredicate<? super T,? super T> smallerEqual) {
return of(() -> this.myIterator().merge(other.myIterator(), smallerEqual));
}
}
public class Test {
public static void main(String[] args) {
MyIterable<Integer> iterable = MyIterable.range(0, 10);
MyIterable<Integer> iter1 = iterable.map(x -> 2 * x).filter(x -> x < 10);
MyIterable<Integer> iter2 = iterable.map(x -> 2 * x + 1).filter(x -> x < 10);
MyIterable<Integer> iterMerged = iter1.merge(iter2, (x, y) -> x <= y);
iter1.forEach(System.out::println);
System.out.println();
iter2.forEach(System.out::println);
System.out.println();
iterMerged.forEach(System.out::println);
}
}
What would probably be more idiomatically "java" is to write your merger with a listener:
public interface Merger {
public Collection<T> merge(Collection<T> left, Collection<T> right, Comparator comparator);
public void addListener(Observer observer);
public void notifyListener(Message message);
}
public interface Observer {
public void notify(Message message);
}
Related
I have to use a type from a 3rd party library that does not have equals and hashCode.
In my example this will be played by the class Box which contains some data.
I have create a custom static method which compares to instances according to the specification. In the example if the data are the same.
The problem is that my implementation still does not take into account the cardinality of the unique instances.
import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.Objects;
import java.util.function.BiPredicate;
import static org.assertj.core.util.Lists.newArrayList;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class CustomEqualsTest {
public static final BiPredicate<Box, Box> EQUALS = CustomEqualsTest::equals;
static boolean equals(Box b1, Box b2) {
if (b1 == b2) {
return true;
}
if (b1 != null && b2 != null) {
return Objects.equals(b1.data, b2.data);
}
return false;
}
static class Box {
Integer data;
private Box(Integer data) {
this.data = data;
}
static Box of(Integer data) {
return new Box(data);
}
// intentionally skip equals
// intentionally skip hashCode
}
#Test
void testCustomEquals() {
assertTrue(equals(
newArrayList(Box.of(1)),
newArrayList(Box.of(1)), EQUALS));
assertFalse(equals(
newArrayList(Box.of(1)),
newArrayList(), EQUALS));
assertFalse(equals(
newArrayList(Box.of(1)),
newArrayList((Box) null), EQUALS));
assertFalse(equals(
newArrayList(Box.of(1)),
newArrayList(Box.of(2)), EQUALS));
assertFalse(equals(
newArrayList(Box.of(1), Box.of(1)),
newArrayList(Box.of(1)), EQUALS));
// This fails:
assertFalse(
equals(
newArrayList(Box.of(1), Box.of(1), Box.of(2)),
newArrayList(Box.of(1), Box.of(2), Box.of(2)),
EQUALS));
}
static <T> boolean equals(Collection<T> collection1, Collection<T> collection2, BiPredicate<T, T> equals) {
if (collection1.size() != collection2.size()) {
return false;
}
for (T t1 : collection1) {
boolean match = false;
for (T t2 : collection2) {
if (equals.test(t1, t2)) {
match = true;
break;
}
}
if (!match) {
return false;
}
}
return true;
}
}
Since you can't provide equals and hashCode, most collections are out of the question. This leaves us only with tree structures(TreeMap to be precise) and custom Comparator to work with. Example null safe comparator:
public static final Comparator<Box> COMPARATOR = Comparator.nullsLast(Comparator.comparing(Box::getData));
Count the elements in each collection using TreeMap
static <T> boolean equals(Collection<T> collection1, Collection<T> collection2, BiPredicate<T, T> equals, Comparator<T> comparator) {
if (collection1.size() != collection2.size()) {
return false;
}
Map<T, Integer> m1 = new TreeMap<>(comparator);
for (T t : collection1) {
m1.merge(t, 1, Integer::sum);
}
Map<T, Integer> m2 = new TreeMap<>(comparator);
for (T t : collection2) {
m2.merge(t, 1, Integer::sum);
}
if (m1.size() != m2.size()) {
return false;
}
Iterator<Map.Entry<T, Integer>> m2Iterator = m2.entrySet().iterator();
for (Map.Entry<T, Integer> m1Entry : m1.entrySet()) {
Map.Entry<T, Integer> m2Entry = m2Iterator.next();
if (!equals.test(m1Entry.getKey(), m2Entry.getKey())) {
return false;
}
if (!m1Entry.getValue().equals(m2Entry.getValue())) {
return false;
}
}
return true;
}
Entries now will be in the same order, so we can safely compare current keys(Box) with current counts.
Other option would be to collect collections to sorted lists and compare each element.
static <T> boolean equals(Collection<T> collection1, Collection<T> collection2, BiPredicate<T, T> equals, Comparator<T> comparator) {
if (collection1.size() != collection2.size()) {
return false;
}
List<T> l1 = collection1.stream().sorted(comparator).collect(Collectors.toList());
List<T> l2 = collection2.stream().sorted(comparator).collect(Collectors.toList());
for (int i = 0; i < l1.size(); i++) {
if (!equals.test(l1.get(i), l2.get(i))) {
return false;
}
}
return true;
}
If collections are guaranteed to be lists and you don't need to keep them in input order, it's possible to sort directly without streaming. I would stick with 2nd option, if possible, it's shorter and more readable i think.
I have a problem with my custom iterator, so I'm asking for your help. I have class MyIterator, which is an iterator with transformation. This class has methods:
next() - returns next element
hasNext() - check if next element exists
fromIterator - static method, which converts Iterator to MyIterator
map - method which takes functional interface and returns MyIterator with transformation rule corresponding to this interface
forEach - method which takes functional interface and iterates over all remaining objects according to the interface. My realisation is
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.function.Function;
public class MyIterator<K, V> {
private final Iterator<K> iterator;
private final Function<K, V> function;
#SuppressWarnings("unchecked")
public static <K, V> MyIterator<K, V> fromIterator(Iterator<K> iterator) {
return new MyIterator<>(iterator, k -> (V) k);
}
private MyIterator(Iterator<K> iterator, Function<K, V> function) {
this.iterator = iterator;
this.function = function;
}
public V next() {
return this.function.apply(iterator.next());
}
public boolean hasNext() {
return this.iterator.hasNext();
}
public MyIterator<K, V> map(Function<K, V> function) {
return new MyIterator<K, V>(this.iterator, this.function);
}
public void forEach(Consumer<V> action) {
while (hasNext()) {
action.accept(this.next());
}
}
}
So, I did this task, but I can't understand, how to change the method map into chaining method (pipeline). I mean the following:
MyIterator<String, Integer> myIterator3 = MyIterator.fromIterator(stringsArray.iterator()).map(s -> s.length()).map(i -> i.toString()).map(s -> s.length());
For example, I have String "England". After first map I want to get 7 ("England" consists of 7 characters), than "7", than 1 (because String "7" consists of 1 character). My assumption is that I should use methods andThen/compose in my method map, by I can't understand, how.
As Iterator accepts one parameter, here is how I modified your code.
public class ChainedIterator<T> {
private Function<T, ?> action;
private ChainedIterator<T> chain;
private final Iterator<?> iterator;
private <R> ChainedIterator(Iterator<?> iterator, Function<T, R> action, ChainedIterator<T> prev) {
this.action = action;
this.chain = prev;
this.iterator = iterator;
}
public static <T> ChainedIterator<T> fromIterator(Iterator<T> iterator) {
return new ChainedIterator<>(iterator, Function.identity(), null);
}
public T next() {
return (T) this.action.apply((T) (Objects.nonNull(this.chain) ? this.chain.next() : this.iterator.next()));
}
public boolean hasNext() {
return this.iterator.hasNext();
}
public <R> ChainedIterator<R> map(Function<T, R> action) {
return new ChainedIterator(this.iterator, action, this);
}
public void forEach(Consumer<T> action) {
while (hasNext()) {
action.accept(this.next());
}
}
}
Usage Example
Iterator<String> stringIterator = Arrays.asList("England", "India").iterator();
ChainedIterator<Integer> iterator = ChainedIterator.fromIterator(stringIterator)
.map(s -> s.length())
.map(i -> String.valueOf(i))
.map(s -> s.length());
I hope this helps :)
Update your custom Iterator and allow fromIterator() takes function rather you define it
public class MyIterator<K, V> {
private Iterator<K> iterator;
private List<Function<K, ?>> functions;
public static <K, V> MyIterator<K, V> fromIterator(Iterator<K> iterator) {
return new MyIterator<>(iterator);
}
private MyIterator(Iterator<K> iterator) {
this.iterator = iterator;
functions = new ArrayList<>();
}
private MyIterator(Iterator<K> iterator, Function<K, ?> function) {
this.iterator = iterator;
functions = new ArrayList<>();
functions.add(function);
}
private MyIterator(Iterator<K> iterator, List<Function<K, ?>> functions) {
this.iterator = iterator;
this.functions = functions;
}
public Object next() {
K key = iterator.next();
Object val = null;
for (int i = 0; i < functions.size(); i++) {
val = functions.get(i).apply(key);
key = (K) val;
}
return val;
}
public boolean hasNext() {
return iterator.hasNext();
}
public <R, RR> MyIterator<R, RR> map(Function<K, R> function) {
List<Function<K, ?>> functions2 = this.functions;
functions2.add(function);
return new MyIterator(iterator, functions2);
}
public void forEach(Consumer<Object> action) {
while (hasNext()) {
action.accept(next());
}
}
}
, main
public static void main(String[] args) throws Exception {
Iterator<String> sIterator = Arrays.asList("aaa", "bbbb", "cccc", "ddddd").iterator();
MyIterator.<String, Object>fromIterator(sIterator).map(s -> s.length()).map(i -> i + "")
.map(str -> str.length()).forEach(System.out::println);
}
, output
1
1
1
1
I want to do a string list filter function using an Iterable<String> and a predicate to select the strings to keep, the other ones must be removed from the list, but I'm not understating how I do the remove.
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
for (T s: it) {
if (pred.test(s)==false) {
// what to do here?
}
}
return ...;
}
For this input:
{"a","","b",""}
I expect
{"a","b"}
An Iterable represents the capability to provide an Iterator on request. So, to decorate an existing iterable with a filtering logic, you have to implement the decorating Iterator.
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return () -> new Iterator<T>() {
Iterator<T> sourceIterator = it.iterator();
T current;
boolean hasCurrent;
#Override
public boolean hasNext() {
while(!hasCurrent) {
if(!sourceIterator.hasNext()) {
return false;
}
T next = sourceIterator.next();
if(pred.test(next)) {
current = next;
hasCurrent = true;
}
}
return true;
}
#Override
public T next() {
if(!hasNext()) throw new NoSuchElementException();
T next = current;
current = null;
hasCurrent = false;
return next;
}
};
}
which you may test via
List<String> original = new ArrayList<>();
Collections.addAll(original, "foo", "bar", "baz");
Iterable<String> filter = select(original, s -> s.startsWith("b"));
System.out.println(String.join(", ", filter));
original.removeIf(s -> !s.endsWith("r"));
System.out.println(String.join(", ", filter));
The biggest challenge when implementing such an Iterator, is to provide the two methods hasNext and next with the correct semantics, without any guaranty regarding how the caller will invoke them, i.e. you can not assume that it will never invoke hasNext() twice nor that next() will always be invoked with a preceding hasNext().
The same logic can be implemented much easier using the Stream API:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return () -> StreamSupport.stream(it.spliterator(), false)
.filter(pred).iterator();
}
Since any Collection is Iterable, just add the qualified items to a new collection and return it later:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
Collection<T> collection = new ArrayList<>();
for (T s: it) {
if (!pred.test(s)) {
collection.add(s);
}
}
return collection;
}
Few insights:
The pred.test(s)==false expression shall be rather simplified to !pred.test(s)
The whole content of method could be shortened using java-stream in this way:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return StreamSupport.stream(it.spliterator(), false)
.filter(pred)
.collect(Collectors.toList());
}
First wrap your Iterable<T> into Stream<T>:
Plain Java:
StreamSupport.stream(it.spliterator(), false)
Guava
Streams.stream(it)
StreamEx
StreamEx.of(it.iterator())
Then filter it by your Predicate<T> :
...
stream.filter(pred.negate())
...
And finally return Iterable<T>:
as lambda :
return () -> stream.iterator();
as method reference
return stream::iterator;
Complete example:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
return StreamSupport.stream(it.spliterator(), false).filter(pred.negate())::iterator;
}
or:
static <T> Iterable<T> select(Iterable<T> it, Predicate<T> pred) {
Stream<T> stream = stream(it.spliterator(), false);
Predicate<T> negatedPred = pred.negate();
Stream<T> filteredStream = stream.filter(negatedPred);
return filteredStream::iterator;
}
The alternative solution to Holger's I meant in the comment looks like this:
static <T> Iterable<T> select(Iterable<T> toIterate, Predicate<T> pred) {
return () -> new Iterator<T>() {
Iterator<T> delegate = toIterate.iterator();
T next = findNextValid();
public boolean hasNext() {
return next != null;
}
public T next() {
if (next == null) throw new NoSuchElementException();
T result = next;
next = findNextValid();
return result;
}
private T findNextValid() {
T result = null;
while (result == null && delegate.hasNext()) {
T candidate = delegate.next();
if (pred.test(candidate)) {
result = candidate;
}
}
return result;
}
};
}
The difference is that there's no need for an additional marker for the hasCurrent, and it advances the Iterator before the next element is actually requested. You might consider the latter to be undesirable though.
I have a method which looks like this:
void foo (List<String> list, ...) {
...
for (String s : list) { // this is the only place where `list` is used
...
}
...
}
the exact same code would work if I replace List<String> list with String[] list, however, to avoid spaghetti code, I keep the single method, and when I need to call it on an array a, I do it like this: foo(Arrays.asList(a)).
I wonder if this is The Right Way.
Specifically,
What is the overhead of Arrays.asList()?
Is there a way to write a method which would accept both arrays and lists, just like the for loop does?
Thanks!
Arrays.asList() has a small overhead. There is no real way to implement one method for both List and arrays.
But you can do the following:
void foo (List<String> list, ...) {
...
for (String s : list) { // this is the only place where *list* is used
...
}
...
}
void foo (String[] arr, ...) {
if ( arr != null ) {
foo(Arrays.asList(arr),...);
}
}
From the source code of openjdk, Arrays.asList:
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
furthermore:
ArrayList(E[] array) {
if (array==null)
throw new NullPointerException();
a = array;
}
So basically all that happens in an assignment, so the overhead should be negligible.
The overhead is that it converts an array to a list--how it does so would be implementation-dependent, it only needs to fulfill the contract.
IMO you should write two methods if you're concerned about the potential runtime overhead: that is the nature of Java; methods have type signatures, and they must be obeyed.
Do avoid this I just use and allow Lists, Sets and Maps (like Joshua Bloch told us). There is no way to merge both "collection types".
An alternative is to use guava (Iterators/Iteratables). So you can iterarte over your collections without a deep copy of them.
Good question.
This is a very common case, and is often dealt with by writing two separate methods. However code duplication is really a bad idea, and whenever you find yourself duplicating code, you should start looking for opportunities to factor your code better. (As you are doing right now!)
Now if you look into the source of java.util.Arrays, you will notice that Arrays.asList retruns an instance of a private inner class Arrays.ArrayList which is just a thin wrapper over plain arrays, and delegates all relevant method calls to it. (This is known as a projection or view of a data structure.) Therefore the overhead incurred is insignificant (unless you are striving to extract every last bit of performance), and in my opinion, you should go ahead and use this method without worrying about performance.
The solution I personally use is as follows.
I have a class named RichIterable in my personal utils. As the name indicates the class wraps over Iterable and provides some additional useful methods not already present. The class also has a factory method that creates an RichIterable from an array. Here is the class definition.
public class RichIterable<A> implements Iterable<A> {
private Iterable<A> xs;
private RichIterable(Iterable<A> xs) {
this.xs = xs;
}
public static <A> RichIterable<A> from(Iterable<A> xs) {
if (xs instanceof RichIterable) {
return (RichIterable<A>) xs;
} else {
return new RichIterable<A>(xs);
}
}
public static <A> RichIterable<A> from(final Enumeration<A> xs) {
Iterable<A> iterable = new Iterable<A>() {
#Override
public Iterator<A> iterator() {
return new Iterator<A>() {
#Override
public boolean hasNext() {
return xs.hasMoreElements();
}
#Override
public A next() {
return xs.nextElement();
}
#Override
public void remove() {
throw new UnsupportedOperationException(
"Cannot remove an element from an enumeration.");
}
};
}
};
return RichIterable.from(iterable);
}
public static <A> RichIterable<A> from(final A[] xs) {
Iterable<A> iterable = new Iterable<A>() {
#Override
public Iterator<A> iterator() {
return new Iterator<A>() {
private int i = 0;
#Override
public boolean hasNext() {
return i < xs.length;
}
#Override
public A next() {
A x = xs[i];
i++;
return x;
}
#Override
public void remove() {
throw new UnsupportedOperationException(
"Cannot remove an element from an array.");
}
};
}
};
return RichIterable.from(iterable);
}
public boolean isEmpty() {
if (xs instanceof Collection) {
return ((Collection) xs).isEmpty();
}
for (A x : xs) {
return false;
}
return true;
}
public int size() {
if (xs instanceof Collection) {
return ((Collection) xs).size();
}
int size = 0;
for (A x : xs) {
size++;
}
return size;
}
public ArrayList<A> toArrayList() {
ArrayList<A> ys = new ArrayList<A>();
for (A x : xs) {
ys.add(x);
}
return ys;
}
public <B> RichIterable<B> map(F1<A, B> f) {
List<B> ys = new ArrayList<B>();
for (A x : xs) {
ys.add(f.apply(x));
}
return RichIterable.from(ys);
}
public RichIterable<A> filter(F1<A, Boolean> pred) {
List<A> ys = new ArrayList<A>();
Arrays.asList();
for (A x : xs) {
if (pred.apply(x)) {
ys.add(x);
}
}
return RichIterable.from(ys);
}
public boolean exists(F1<A, Boolean> pred) {
for (A x : xs) {
if (pred.apply(x)) {
return true;
}
}
return false;
}
public boolean forall(F1<A, Boolean> pred) {
for (A x : xs) {
if (!pred.apply(x)) {
return false;
}
}
return true;
}
public Maybe<A> find(F1<A, Boolean> pred) {
for (A x : xs) {
if (pred.apply(x)) {
return Just.of(x);
}
}
return Nothing.value();
}
public String mkString(String beg, String sep, String end) {
Iterator<A> i = xs.iterator();
if (!i.hasNext()) {
return beg + end;
}
StringBuilder sb = new StringBuilder();
sb.append(beg);
while (true) {
A e = i.next();
sb.append(e.toString());
if (!i.hasNext()) {
return sb.append(end).toString();
}
sb.append(sep);
}
}
public String mkString(String sep) {
return mkString("", sep, "");
}
public String mkString() {
return this.mkString(", ");
}
public Iterable<A> getRaw() {
return xs;
}
#Override
public Iterator<A> iterator() {
return xs.iterator();
}
}
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
}
}