The question but in C#. So does Java have C#'s command? I need it for Matches-SearchTerm-Files-relationship.
foreach(var i in BunchOfItems.SelectMany(k => k.Items)) {}
[Why not for-loops?]
I have done such structures in nested for loops but they soon become bloated. So I prefer something more succint like the above.
public static Stack<Integer[]> getPrintPoss(String s,File f,Integer maxViewPerF)
{
Stack<File> possPrint = new Stack<File>();
Integer[] poss = new Integer[4]();
int u,size;
for(File f:files)
{
size = f2S(f).length();
u = Math.min(maxViewsPerF,size);
for(int i=0; i<u;i++)
{
// Do something --- bloated, and soon out of control
// wants more succintly
}
}
return possPrint;
}
for (List<Object> lo : list) {
for (Object o : lo) {
// etc etc
}
}
I don't think there's a simpler solution.
If you can get the data into an Iterable<Iterable<T>>, then you can get from that to a flattened Iterable<T> using Guava's Iterables.concat method. If what you have is really an Iterable<S>, with some way to get from an S to an Iterable<T>, well, then you have to first use Iterables.transform to view that as the Iterable<Iterable<T>> needed by concat.
All this will look a lot nicer if and when Java has something resembling closures, but at least today it's possible.
http://guava-libraries.googlecode.com
With Java 8, you can say
Collection bunchOfItems = ...;
bunchOfItems.stream().flatMap(k::getItems).forEach(i -> /* operate on i */);
or
Item[] bunchOfItems = ...;
Stream.of(bunchOfItems).flatMap(k::getItems).forEach(i -> /* operate on i */);
depending upon whether you have a Collection or an Array.
Have about half a year patience until JDK7 is final which will include Closures. This provides simliar syntax and the same possibilities as LINQ which was demonstrated in the answer you're talking about.
I have my own version. Waiting desperately for Closures in Java :
public static <T, E> Iterable<T> transformMany(Iterable<E> iterable, Func<E, Iterable<T>> f) {
if (null == iterable)
throw new IllegalArgumentException("null iterable");
if (null == f)
throw new IllegalArgumentException("null f");
return new TransformManyIterable<E, T>(iterable, f);
}
public interface Func<E, T> {
T execute(E e);
}
public class TransformManyIterable<TOriginal, TResult> implements Iterable<TResult> {
private Iterable<TOriginal> iterable;
private Func<TOriginal, Iterable<TResult>> func;
public TransformManyIterable(Iterable<TOriginal> iterable,
Func<TOriginal, Iterable<TResult>> func) {
super();
this.iterable = iterable;
this.func = func;
}
class TransformIterator implements Iterator<TResult> {
private Iterator<TOriginal> iterator;
private Iterator<TResult> currentIterator;
public TransformIterator() {
iterator = iterable.iterator();
}
#Override
public boolean hasNext() {
if (currentIterator != null && currentIterator.hasNext())
return true;
else {
while (iterator.hasNext()) {
Iterable<TResult> iterable = func.execute(iterator.next());
if (iterable == null)
continue;
currentIterator = iterable.iterator();
if (currentIterator.hasNext())
return true;
}
}
return false;
}
#Override
public TResult next() {
if (currentIterator != null && currentIterator.hasNext())
return currentIterator.next();
else {
while (iterator.hasNext()) {
Iterable<TResult> iterable = func.execute(iterator.next());
if (iterable == null)
continue;
currentIterator = iterable.iterator();
if (currentIterator.hasNext())
return currentIterator.next();
}
}
throw new NoSuchElementException();
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
#Override
public Iterator<TResult> iterator() {
return new TransformIterator();
}
}
Usage:
Iterable<SomeType> result = transformMany(input, new Func<InputType, Iterable<SomeType>>() {
#Override
public Iterable<SomeType> execute(InputType e) {
return new ArrayList<SomeType>();
}
});
The SelectMany method is part of LINQ which is .Net-specific. This question asks about a LINQ equilvalent for java. Unfortunately, it doesn't look like there is a direct equivalent.
Related
I'm doing kind of a 'decorator' to List Collection in Java. Sth is wrong and i have no idea what it is. Here is my code and observed error.
1. myListContainer.java
public class myListContainer<T> implements List<T>{
List<T> basicList;
public myListContainer(List<T> basicList) {
this.basicList = basicList;
}
#Override
public Iterator<T> iterator() {
return new myIterator();
}
private class myIterator implements Iterator<T>{
int actIndex;
int visitTwice;
public myIterator() {
this.actIndex = 0;
this.visitTwice = 0;
}
#Override
public boolean hasNext() {
if (actIndex < basicList.size() - 1)
return true;
else if (actIndex == basicList.size() - 1 &&visitTwice < 1)
return true;
return false;
}
#Override
public T next() {
if (this.hasNext()) {
if (visitTwice < 1) {
visitTwice = 1;
return basicList.get(actIndex);
} else {
visitTwice = 0;
return basicList.get(actIndex++);
}
}
throw new ArrayIndexOutOfBoundsException();
}
}
//implementation of methods form List<T> interface
}
2. Client.java (psvm) AND A PROBLEM
public class Client {
List<String> test = new myListContainer<>(Arrays.asList("Janek",
"Bartek", "Stefan", "Horacy", "Jakub", "Antoni"));
boolean bl = test.iterator().hasNext(); //ok,
Iterator iter = test.iterator();
iter.hasNext(); //not ok, cannot resolve hasNext
}
PROBLEM:
1. test.iterator().hasNext() WORKS Fine
2. iter.hasNext() DOESN'T WORK, it is not visible(hasNext), 'Cannot resolve symbol'
EDIT: Certainly all files are in one module, and has necessary imports.
The problem is the scope of the call, in this scope of the class you should initialize or declare members/instance-variables.
This is works - boolean bl = test.iterator().hasNext(); //ok,
Iterator iter = test.iterator(); because it's a declarations of a class members.
So if yo'll try to call hasNext() in function scope- it will work. see example:
public class Client {
List<String> test = new myListContainer<>(Arrays.asList("Janek",
"Bartek", "Stefan", "Horacy", "Jakub", "Antoni"));
boolean bl = test.iterator().hasNext(); //ok,
Iterator iter = test.iterator();
public void foo() {
while (iter.hasNext()) { // here it will work!
}
}
}
I am very sorry, accidentally i deleted my main function and it was a problem. Sorry again.
QUESTION COULD BE DELETED, its just my simple mistake, sorry.
I have Set with items, and want to send it for parallel processing.
However, I want to modify the original set afterwards and it'd cause some concurrency issues, so I think it'd be nice to take a snapshot or something of the Set and send THAt for the processing.
Will clone work good?
Or should I make a new Set of it myself?
Or is there some nice way I'm missing?
Edit: I'm now using this, it seems to work pretty nice:
public class BufferedHashSet<E> extends HashSet<E> {
private List<E> toAdd = new LinkedList<E>();
private List<Object> toRemove = new LinkedList<Object>();
#Override
public boolean add(E e)
{
synchronized (this) {
toAdd.add(e);
return true;
}
}
#Override
public boolean remove(Object e)
{
synchronized (this) {
toRemove.add(e);
return true;
}
}
public void flush()
{
synchronized (this) {
for (E e : toAdd) {
super.add(e);
}
for (Object e : toRemove) {
super.remove(e);
}
toAdd.clear();
toRemove.clear();
}
}
}
In my opinion the most elegant solution is to use Set.addAll() method.
Set set;
Set snapshot = new TreeSet<>(); //or any Set implementation you use
snapshot.addAll(set);
I just started playing around Java 8 and Lambda Expression and I am curious if I can stop the Stream generation from inside the Lambda expession by returning a specific value
(like null). Is this possible with Stream.generate()?
private int counter;
private void generate()
{
System.out.println(Stream.generate(() -> {
if (counter < 10) {
counter++;
return RandomUtils.nextInt(100);
} else {
return null;
}
}).count());
}
Unfortunately this code does not terminate, so by simply returning null will not step out of the stream.
Java 9 and later includes this method:
Stream<T> takeWhile(Predicate<? super T> predicate);
to limit a stream by condition. So the workaround beneath is not needed anymore.
Original answer (for Java versions earlier than 9):
With Stream.generate this is per definition not possible from a lambda closure. It is by definition endless. Using limit() you are able make your stream fix sized. But this will not help you for conditions like:
if random>10 then stop
There is a possibility to limit a potential endless stream by condition. This is usefull if one does not know the size. Your friend here is a Spliterator and your sample code would look like:
System.out.println( StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<Integer>() {
int counter = 0;
#Override
public boolean hasNext() {
return counter < 10;
}
#Override
public Integer next() {
counter++;
return RandomUtils.nextInt(100);
}
}, Spliterator.IMMUTABLE), false).count());
Basically you are able to build a Stream from an Iterator. I am using this construct e.g. for a stream of XMLEvents from Stax XML - parsing.
I know this is not done by lambda constructs but it IHMO solves this lacking feature of stopping the stream item generation by condition.
I would be very interested, if there is a better way to achieve this (I mean this stream construct and not the XML processing ;)) or if there is a fundamental flaw in using streams in this way.
This is not possible with Lamdas, you cannot control the flow from inside the expression.
Even the API docs says that the Stream.generate generates an infinite stream.
However, you can limit the Stream and achieve the desired functionality simply by using the limit() method:
System.out.println(Stream.generate(() -> RandomUtils.nextInt(100)).limit(10).count());
// If you are not looking for parallelism, you can use following method:
public static <T> Stream<T> breakStream(Stream<T> stream, Predicate<T> terminate) {
final Iterator<T> original = stream.iterator();
Iterable<T> iter = () -> new Iterator<T>() {
T t;
boolean hasValue = false;
#Override
public boolean hasNext() {
if (!original.hasNext()) {
return false;
}
t = original.next();
hasValue = true;
if (terminate.test(t)) {
return false;
}
return true;
}
#Override
public T next() {
if (hasValue) {
hasValue = false;
return t;
}
return t;
}
};
return StreamSupport.stream(iter.spliterator(), false);
}
Use StreamSupport.stream(Spliterator, boolean)
See JavaDoc on Spliterator.
Here is example spliterator:
public class GeneratingSpliterator<T> implements Spliterator<T>
{
private Supplier<T> supplier;
private Predicate<T> predicate;
public GeneratingSpliterator(final Supplier<T> newSupplier, final Predicate<T> newPredicate)
{
supplier = newSupplier;
predicate = newPredicate;
}
#Override
public int characteristics()
{
return 0;
}
#Override
public long estimateSize()
{
return Long.MAX_VALUE;
}
#Override
public boolean tryAdvance(final Consumer<? super T> action)
{
T newObject = supplier.get();
boolean ret = predicate.test(newObject);
if(ret) action.accept(newObject);
return ret;
}
#Override
public Spliterator<T> trySplit()
{
return null;
}
}
This is another solution for java 8 (It needs a Stream.Builder, may be it is not optimal, but it is quite simple):
#SuppressWarnings("ResultOfMethodCallIgnored")
public static <T> Stream<T> streamBreakable(Stream<T> stream, Predicate<T> stopCondition) {
Stream.Builder<T> builder = Stream.builder();
stream.map(t -> {
boolean stop = stopCondition.test(t);
if (!stop) {
builder.add(t);
}
return stop;
})
.filter(result -> result)
.findFirst();
return builder.build();
}
And the test:
#Test
public void shouldStop() {
AtomicInteger count = new AtomicInteger(0);
Stream<Integer> stream = Stream.generate(() -> {
if (count.getAndIncrement() < 10) {
return (int) (Math.random() * 100);
} else {
return null;
}
});
List<Integer> list = streamBreakable(stream, Objects::isNull)
.collect(Collectors.toList());
System.out.println(list);
}
It is possible, you just need to think outside the box.
The following idea is borrowed from Python, the language which introduced me to generator functions...
Just throw an instance of RuntimeException when you are done from within the Supplier<T> closure and catch-and-ignore it at the call site.
An example excerpt (note I have added a safety catch of Stream.limit(Long.MAX_VALUE) to cover the unexpected, though it should never be triggered):
static <T> Stream<T> read(String path, FieldSetMapper<T> fieldSetMapper) throws IOException {
ClassPathResource resource = new ClassPathResource(path);
DefaultLineMapper<T> lineMapper = new DefaultLineMapper<>();
lineMapper.setFieldSetMapper(fieldSetMapper);
lineMapper.setLineTokenizer(getTokenizer(resource));
return Stream.generate(new Supplier<T>() {
FlatFileItemReader<T> itemReader = new FlatFileItemReader<>();
int line = 1;
{
itemReader.setResource(resource);
itemReader.setLineMapper(lineMapper);
itemReader.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy());
itemReader.setLinesToSkip(1);
itemReader.open(new ExecutionContext());
}
#Override
public T get() {
T item = null;
++line;
try {
item = itemReader.read();
if (item == null) {
throw new StopIterationException();
}
} catch (StopIterationException ex) {
throw ex;
} catch (Exception ex) {
LOG.log(WARNING, ex,
() -> format("%s reading line %d of %s", ex.getClass().getSimpleName(), line, resource));
}
return item;
}
}).limit(Long.MAX_VALUE).filter(Objects::nonNull);
}
static class StopIterationException extends RuntimeException {}
public void init() {
if (repository.count() == 0) {
Level logLevel = INFO;
try {
read("providers.csv", fields -> new Provider(
fields.readString("code"),
fields.readString("name"),
LocalDate.parse(fields.readString("effectiveStart"), DateTimeFormatter.ISO_LOCAL_DATE),
LocalDate.parse(fields.readString("effectiveEnd"), DateTimeFormatter.ISO_LOCAL_DATE)
)).forEach(repository::save);
} catch (IOException e) {
logLevel = WARNING;
LOG.log(logLevel, "Initialization was interrupted");
} catch (StopIterationException ignored) {}
LOG.log(logLevel, "{} providers imported.", repository.count());
}
}
My solution was to generate a null when done and then apply a filter
Stream
.generate( o -> newObject() )
.filter( o -> o != null )
.forEach(...)
Design an iterator for a collection of collections in java. The iterator should hide the nesting, allowing you to iterate all of the elements belonging to all of the collections as if you were working with a single collection
This is an old question, but nowadays (2019) we have JDK8+ goodies. In particular, we have streams, which make this task straightforward:
public static <T> Iterator<T> flatIterator(Collection<Collection<T>> collections) {
return collections.stream()
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.iterator();
}
I'm filtering null inner collections out, just in case...
EDIT: If you also want to filter null elements out of the inner collections, just add an extra non-null filter aflter flatMap:
return collections.stream()
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.iterator();
Here is a possible implementation. Note that I left remove() unimplemented:
public class MultiIterator <T> implements Iterator<T>{
private Iterator<? extends Collection<T>> it;
private Iterator<T> innerIt;
private T next;
private boolean hasNext = true;
public MultiIterator(Collection<? extends Collection<T>> collections) {
it = collections.iterator();
prepareNext();
}
private void prepareNext() {
do {
if (innerIt == null || !innerIt.hasNext()) {
if (!it.hasNext()) {
hasNext = false;
return;
} else
innerIt = it.next().iterator();
}
} while (!innerIt.hasNext());
next = innerIt.next();
}
#Override
public boolean hasNext() {
return hasNext;
}
#Override
public T next() {
if (!hasNext)
throw new NoSuchElementException();
T res = next;
prepareNext();
return res;
}
#Override
public void remove() {
//TODO
}
}
In this post you can see two implementations, the only (minor) difference is that it takes an iterator of iterators instead of a collection of collections.
This difference combined with the requirement to iterate the elements in a round-robin fashion (a requirement that wasn't requested by the OP in this question) adds the overhead of copying the iterators into a list.
The first approach is lazy: it will iterate an element only when this element is requested, the 'price' we have to pay is that the code is more complex because it needs to handle more edge-cases:
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
public class MultiIterator<E> implements Iterator {
List<Iterator<E>> iterators = new LinkedList<>();
Iterator<E> current = null;
public MultiIterator(Iterator<Iterator<E>> iterator) {
// copy the iterators into a list
while (iterator.hasNext()) {
iterators.add(iterator.next());
}
}
#Override
public boolean hasNext() {
boolean result = false;
if (iterators.isEmpty() && (current == null || !current.hasNext())) {
return false;
}
if (current == null) {
current = iterators.remove(0);
}
while (!current.hasNext() && !iterators.isEmpty()) {
current = iterators.remove(0);
}
if (current.hasNext()) {
result = true;
}
return result;
}
#Override
public E next() {
if (current == null) {
try {
current = iterators.remove(0);
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
E result = current.next(); // if this method was called without checking 'hasNext' this line might raise NoSuchElementException which is fine
iterators.add(current);
current = iterators.remove(0);
return result;
}
// test
public static void main(String[] args) {
List<Integer> a = new LinkedList<>();
a.add(1);
a.add(7);
a.add(13);
a.add(17);
List<Integer> b = new LinkedList<>();
b.add(2);
b.add(8);
b.add(14);
b.add(18);
List<Integer> c = new LinkedList<>();
c.add(3);
c.add(9);
List<Integer> d = new LinkedList<>();
d.add(4);
d.add(10);
d.add(15);
List<Integer> e = new LinkedList<>();
e.add(5);
e.add(11);
List<Integer> f = new LinkedList<>();
f.add(6);
f.add(12);
f.add(16);
f.add(19);
List<Iterator<Integer>> iterators = new LinkedList<>();
iterators.add(a.iterator());
iterators.add(b.iterator());
iterators.add(c.iterator());
iterators.add(d.iterator());
iterators.add(e.iterator());
iterators.add(f.iterator());
MultiIterator<Integer> it = new MultiIterator<>(iterators.iterator());
while (it.hasNext()) {
System.out.print(it.next() + ","); // prints: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
}
}
}
and the second ('greedy' copying of all the elements from all the iterators in the requested order into a list and returning an iterator to that list ):
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class MultiIterator<E> {
Iterator<Iterator<E>> iterator = null;
List<E> elements = new LinkedList<>();
private MultiIterator(Iterator<Iterator<E>> iterator) {
this.iterator = iterator;
}
private void copyElementsInOrder() {
List<Iterator<E>> iterators = new LinkedList<>();
// copy the iterators into a list
while (iterator.hasNext()) {
iterators.add(iterator.next());
}
// go over the list, round-robin, and grab one
// element from each sub-iterator and add it to *elements*
// empty sub-iterators will get dropped off the list
while (!iterators.isEmpty()) {
Iterator<E> subIterator = iterators.remove(0);
if (subIterator.hasNext()) {
elements.add(subIterator.next());
iterators.add(subIterator);
}
}
}
public static <E> Iterator<E> iterator(Iterator<Iterator<E>> iterator) {
MultiIterator<E> instance = new MultiIterator<>(iterator);
instance.copyElementsInOrder();
return instance.elements.iterator();
}
// test
public static void main(String[] args) {
List<Integer> a = new LinkedList<>();
a.add(1);
a.add(7);
a.add(13);
a.add(17);
List<Integer> b = new LinkedList<>();
b.add(2);
b.add(8);
b.add(14);
b.add(18);
List<Integer> c = new LinkedList<>();
c.add(3);
c.add(9);
List<Integer> d = new LinkedList<>();
d.add(4);
d.add(10);
d.add(15);
List<Integer> e = new LinkedList<>();
e.add(5);
e.add(11);
List<Integer> f = new LinkedList<>();
f.add(6);
f.add(12);
f.add(16);
f.add(19);
List<Iterator<Integer>> iterators = new LinkedList<>();
iterators.add(a.iterator());
iterators.add(b.iterator());
iterators.add(c.iterator());
iterators.add(d.iterator());
iterators.add(e.iterator());
iterators.add(f.iterator());
Iterator<Integer> it = MultiIterator.<Integer>iterator(iterators.iterator());
while (it.hasNext()) {
System.out.print(it.next() + ","); // prints: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
}
}
}
I included a simple 'test' code in order to show the way to use the MultiIterator, this is not always trivial (because of the use of Generics) as you can see on the line:
Iterator<Integer> it = MultiIterator.<Integer>iterator(iterators.iterator());
Here is another implementation:
import java.util.Iterator;
import java.util.NoSuchElementException;
import static java.util.Collections.emptyIterator;
public class Multiterator<E> implements Iterator<E> {
private Iterator<Iterator<E>> root;
private Iterator<E> current;
public Multiterator(Iterator<Iterator<E>> root) {
this.root = root;
current = null;
}
#Override
public boolean hasNext() {
if (current == null || !current.hasNext()) {
current = getNextNonNullOrEmpty(root);
}
return current.hasNext();
}
private Iterator<E> getNextNonNullOrEmpty(Iterator<Iterator<E>> root) {
while (root.hasNext()) {
Iterator<E> next = root.next();
if (next != null && next.hasNext()) {
return next;
}
}
return emptyIterator();
}
#Override
public E next() {
if (current == null) {
throw new NoSuchElementException();
}
return current.next();
}
}
First, take a look at the implementation of the iterator in java.util.LinkedList
http://www.docjar.com/html/api/java/util/LinkedList.java.html
From there your task is easy just implement a single iterator that takes into account the fact that it is iterating over collections.
Regards.
if all you have to work with is the java Iterator: which just have hasNext(), next() and remove(), i figured you have to go around it.
Process it as you will process a 2D array, that is, with an outer and inner loop, because they have same "arrangement" but different datatype. As you process, you transfer them to a new collection.
so maybe a private method:
private void convertToSingleCollection()
{
while("column")
{
//convert the "column" to an arra
for( "Row")
{
//add to newCollection here
}
//remove the processed column from CollectionOFcollection
}
}
//call the above method in your constructor
public iterator<T> Iterator()
{
newCollection.iterator();
}
public boolean hasNext()
{
return Iterator().hasNext()
}
public T next()
{
if(!hasNext())
{
//exception message or message
}
else
//return "next"
}
end
I hope this helps. There should be other ways to solve it i guess.
I have a list of hosts in an array which represnt the servers available to do a particular job. Currently I simply iterate thru the list looking and establish comms with a host to check its not busy. If not I will send a job to it. This approach tends to mean that the first host in the list tends to get hot constanly with the load not balanced properly with the rest of the available hosts.
in pseudocode ..
for (Host h : hosts) {
//checkstatus
if status == job accepted break;
}
I'd like to balance this load properly between the hosts i.e first time host one is used 2nd time the method is used host 2. Just wondering that the most elegant solution to this is ??
Thanks
W
Google collections has a utility method Iterators.cycle(Iterable<T> iterable) that does what you want.
You can create a new kind of Iterable that provides round-robin iteration:
public class RoundRobin<T> implements Iterable<T> {
private List<T> coll;
public RoundRobin(List<T> coll) { this.coll = coll; }
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
#Override
public boolean hasNext() {
return true;
}
#Override
public T next() {
T res = coll.get(index);
index = (index + 1) % coll.size();
return res;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
You need to define your hosts as RoundRobin<Host>.
[FIXED based on Mirko's comment]
If the list is mutable and the cost of editing it is negligible compared to I/O with the hosts, you can just rotate it:
List<String> list = Arrays.asList("one", "two", "three");
Collections.rotate(list, -1);
System.out.println(list);
IMHO the standard Java API already provides an easy way to accomplish this, without resorting to external libraries or even the need to implement a custom Iterator. Simply use a Deque where you'd pull the first server, use or discard it, then append it back to the end of the Deque. Here's some sample code:
// Initialize the Deque. This might be at your class constructor.
Deque<Host> dq = new ArrayDeque<Host>();
dq.addAll(Arrays.asList(hosts));
void sendJob(Job myJob) {
boolean jobInProcess = false;
do {
Host host = dq.removeFirst(); // Remove the host from the top
if(!host.isBusy()) {
host.sendJob(myJob);
jobInProcess = true;
}
dq.addLast(host); // Put the host back at the end
}
while(!jobInProcess); // Might add another condition to prevent an infinite loop...
}
This is just a sample where you always ping hosts in round robin order in a loop that only ends when one of them is available and takes the job. You could tinker with it easily to go only around the queue once (use a counter with a max set to the queue's size) or a number of times beofre throwing an exception, or sleeping in between rounds to avoid banging the hosts when all are busy.
My RoundRobin implementation, based upon the implementation of https://stackoverflow.com/a/2041772/1268954
/**
*
* #author Mirko Schulze
*
* #param <T>
*/
public class RoundRobin<T> implements Iterable<T> {
private final List<T> coll;
public RoundRobin(final List<T> coll) {
this.coll = NullCheck.throwExceptionIfNull(coll, "collection is null");
}
#Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index;
#Override
public boolean hasNext() {
return true;
}
#Override
public T next() {
this.index = this.index % RoundRobin.this.coll.size();
final T t = RoundRobin.this.coll.get(this.index);
this.index++;
return t;
}
#Override
public void remove() {
throw new IllegalArgumentException("remove not allowd");
}
};
}
}
And the Junit TestCase
/**
*
* #author Mirko Schulze
*
*/
#RunWith(JUnit4.class)
public class RoundRobinTest extends TestCase {
private List<Integer> getCollection() {
final List<Integer> retval = new Vector<Integer>();
retval.add(Integer.valueOf(1));
retval.add(Integer.valueOf(2));
retval.add(Integer.valueOf(3));
retval.add(Integer.valueOf(4));
retval.add(Integer.valueOf(5));
return retval;
}
#Test
public void testIteration() {
final List<Integer> l = this.getCollection();
final Integer frst = l.get(0);
final Integer scnd = l.get(1);
final Integer thrd = l.get(2);
final Integer frth = l.get(3);
final Integer last = l.get(4);
Assert.assertEquals("die Collection hat für diesen Test nicht die passende Größe!", 5, l.size());
final RoundRobin<Integer> rr = new RoundRobin<Integer>(l);
final Iterator<Integer> i = rr.iterator();
for (int collectionIterations = 0; collectionIterations < 4; collectionIterations++) {
final Integer i1 = i.next();
Assert.assertEquals("nicht das erste Element", frst, i1);
final Integer i2 = i.next();
Assert.assertEquals("nicht das zweite Element", scnd, i2);
final Integer i3 = i.next();
Assert.assertEquals("nicht das dritte Element", thrd, i3);
final Integer i4 = i.next();
Assert.assertEquals("nicht das vierte Element", frth, i4);
final Integer i5 = i.next();
Assert.assertEquals("nicht das letzte Element", last, i5);
}
}
}
The implementations provided are buggy and might fail in case of parallelism , the easiest way i did it was to use a circular linked list whose pointer is maintained by an atomic integer.
If you are creating an Iterator, best to create a defensive copy first and have the iterator work on that.
return new MyIterator(ImmutableList.<T>copyOf(list));
public class RoundRobinIterator<T> implements Serializable {
private static final long serialVersionUID = -2472203060894189676L;
//
private List<T> list;
private Iterator<T> it;
private AtomicInteger index = new AtomicInteger(0);
public RoundRobinIterator(List<T> list) throws NullPointerException {
super();
if (list==null) {
throw new NullPointerException("List is null");
}
this.list=Collections.unmodifiableList(list);
}
public RoundRobinIterator(Collection<T> values) {
this(new ArrayList<T>(values));
}
public RoundRobinIterator(Iterator<T> values) {
this(copyIterator(values));
}
public RoundRobinIterator(Enumeration<T> values) {
this(Collections.list(values));
}
private final List<T> getList() {
return list;
}
private final Iterator<T> getIt() {
return it;
}
public final int size() {
return list.size();
}
public final synchronized T getNext(Filter<T> filter) {
int start = index.get();
T t = getNext();
T result = null;
while ((result==null) && (start!=getIndex())) {
if (filter.accept(t)) {
result=t;
} else {
t = getNext();
}
}
return result;
}
public final synchronized T getNext() {
if (getIt()==null) {
if (getList().size()==0) {
index.set(0);
return null;
} else {
it = getList().iterator();
index.set(0);
return it.next();
}
} else if (it.hasNext()) {
index.incrementAndGet();
return it.next();
} else {
if (list.size()==0) {
index.set(0);
return null;
} else {
index.set(0);
it = list.iterator();
return it.next();
}
}
}
public final synchronized int getIndex() {
return index.get();
}
private static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext()) {
copy.add(iter.next());
}
return copy;
}
}
Where Filter is
public interface Filter<T> {
public boolean accept(T t);
}