Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clone an Iterator in Java?

Tags:

In a game I have a list of players, let's say like this:

LinkedList<String> players = new LinkedList<String>();

I want to let each player interact with each of the other players, so I write two nested loops:

Iterator<String> i1 = players.iterator();
while (i1.hasNext()) {
    String p1 = i1.next();
    Iterator<String> i2 = players.iterator();
    // But I want to do this: Iterator<String> i2 = i1.clone();
    while (i2.hasNext()) {
        String p2 = i2.next();
        System.out.println("Interact: " + p1 + ", " + p2);
    }
}

Since I only want each pair of players to interact once, I want to start the inner loop with the player after the outer loop's current player. So I want to clone the iterator, but that doesn't compile.

So, what should I do instead?

like image 382
Thomas Padron-McCarthy Avatar asked Oct 13 '11 17:10

Thomas Padron-McCarthy


People also ask

What is iterator () in Java?

Iterator takes the place of Enumeration in the Java Collections Framework. Iterators differ from enumerations in two ways: Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics. Method names have been improved.

What is hasNext in Java iterator?

The hasNext() method of ListIterator interface is used to return true if the given list iterator contains more number of element during traversing the given list in the forward direction.

How do I clone a list?

To clone a list, one can iterate through the original list and use the clone method to copy all the list elements and use the add method to append them to the list. Approach: Create a cloneable class, which has the clone method overridden. Create a list of the class objects from an array using the asList method.


2 Answers

The following will do it:

ListIterator<String> i1 = players.listIterator(0);
while (i1.hasNext()) {
    String p1 = i1.next();
    ListIterator<String> i2 = players.listIterator(i1.nextIndex());
    while (i2.hasNext()) {
        String p2 = i2.next();
        System.out.println("Interact: " + p1 + ", " + p2);
    }
}

It relies on the ListIterator's ability to start from the given position and to also know its current position.

like image 57
NPE Avatar answered Sep 18 '22 11:09

NPE


In addition to aix answer, I'd like to point out that however you create an iterator starting at a specific index, it's bound to be a linear operation. If it wasn't, you would be able to do arbitrary access to the list in constant time using

elementN = createIterator(linkedList, N).next();

which would be contradictory.

In your situation I therefore believe that the most efficient solution would actually be to do

List<String> tmp = new ArrayList<String>(players);
for (int p1 = 0; p1 < tmp.size(); p1++)
    for (int p2 = p1+1; p2 < tmp.size(); p2++)
        System.out.println("Interact: " + tmp.get(p1) + ", " + tmp.get(p2));

Note however, that it is still the same complexity as the solution by aix; O(n2) but probably with a smaller constant factor.

like image 41
aioobe Avatar answered Sep 16 '22 11:09

aioobe