2

I have a method that takes any iterable object type with unknown type T, and loops through it taking the items out of it and putting it into another data structure. I need to delete each item from the old iterable object as I go so I can re-add the items to it in sorted order.

I tried using .clear() on the object after looping, but it's not guaranteed to have a clear method. So how can I delete items as I go through it, or maybe make a new object with the same exact type but no values so I can re-add everything to it, only knowing that the object is Iterable?

public class PriorityQueue<K extends Comparable<? super K>,V> {

  public static <K> void PriorityQueueSort(Iterable<? extends K> list,
        PriorityQueue<? super K, ?> queue) {

      for (K item : list) {
          queue.insert(item, null);
      }

      list.clear();
  }
}
Mirrana
  • 1,601
  • 6
  • 28
  • 66
  • 1
    Take a look at the answer here for an example of `remove()` http://stackoverflow.com/questions/1196586/calling-remove-in-foreach-loop-in-java – Matt Busche Mar 08 '13 at 14:39

3 Answers3

3

Instead of using a for-each loop, use an explicit Iterator object and Iterator.remove():

    Iterator<K> iter = list.iterator();
    while (iter.hasNext()) {
        K item = iter.next();
        queue.insert(item, null);
        iter.remove();
    }

Bear in mind that not every Iterator implementation supports object removal (for example, read-only collections won't).

NPE
  • 486,780
  • 108
  • 951
  • 1,012
1

You have to use an Iterator to walk through your list. The iterator supports a remove method.

FrVaBe
  • 47,963
  • 16
  • 124
  • 157
1

All collections are Iterables but the opposite is not true. So you can't even expect that removing something from the datasources that produces the iterator items always makes sense. Like in this pretty complicated hello world example:

Iterable<Character> myIterable = new Iterable<Character>() {

    @Override
    public Iterator<Character> iterator() {
        Iterator<Character> it = new Iterator<Character>() {

            private String hello = "Hello World";
            private int counter = 0;

            @Override
            public boolean hasNext() {
                return counter < hello.length();
            }

            @Override
            public Character next() {
                return hello.charAt(counter++);
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }

        };
        return it;
    }
};

for (Character c : myIterable) {
    System.out.print(c);
}

There is no collection backing the Iterable. It is just an "iterator provider" and even that only has a string (and we can't remove chars from a string, a string is immutable).

So no, you can't "clear any iterable" and not every iterator supports removing items.

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268