Iterator isEmpty() call causing noSuchElement exception?

16,116

Solution 1

visibleTiles.isEmpty()

just checks whether map is empty (or) it has any elements.

ile = visibleTiles.keySet().iterator().next();

retrieves next element from iterator.

You need to do hasNext() check before doing next() on iterator.

hasNext() javadoc says

Returns true if the iteration has more elements. (In other words, returns true if next would return an element rather than throwing an exception.)

so, if no element is available and call next() on iterator will return NoSuchElementException.

On top of this, I think you really would like to do NOT empty check

while (!visibleTiles.isEmpty())) {
....
}

Solution 2

while (visibleTiles.keySet().iterator().hasNext()) creates a new Iterator every time it is called*. If visibleTiles is not empty, this will always be true, as the next method of the respective iterator is never called and the internal pointer never advances.

Iterators should be used like this:

Iterator<TileType> tileIt = visibleTiles.keySet().iterator();
while (tileIt.hasNext()) {
    TileType tile = tileIt.next();
    // ...
}

*The point here is that there may be several iterators referring to the same collection at the same time. Each iterator has its own internal state storing (not necessarily explicitly) which element was returned last and which shall be returned next by the next()call. This can be useful, for example, do perform some operation on all pairs of elements from a collection, where two iterators are needed.

Solution 3

You can use com.google.common.collect.Iterables class for empty check on Iterable values.

Iterables.isEmpty(yourIterable)
Share:
16,116
kevinl
Author by

kevinl

#SOreadytohelp

Updated on June 04, 2022

Comments

  • kevinl
    kevinl almost 2 years

    I currently have the following code

    while (!visibleTiles.isEmpty())) {
        tile = visibleTiles.keySet().iterator().next();
        if (tile != null){
            bitmap = visibleTiles.remove(tile);
            if(bitmap != null && !containsKey(tile)){ //safe to recycle if tile cache is not actively holding it
                bitmap.recycle();
            }
        }
    }
    

    However, I get a NoSuchElementException crash on the line

    tile = visibleTiles.keySet().iterator().next();
    

    Is there a big difference in using the isEmpty() method and calling a hasNext() call? I know that hashmaps do not have a hasNext() call so I did the following:

    while (visibleTiles.keySet().iterator().hasNext()) {
        tile = visibleTiles.keySet().iterator().next();
        if (tile != null){
            bitmap = visibleTiles.remove(tile);
            if(bitmap != null && !containsKey(tile)){ //safe to recycle if tile cache is not actively holding it
                bitmap.recycle();
            }
        }
    }
    

    Obviously, I know that I should just run the app and see if it crashes, but the issue is that it's difficult to reproduce the problem.

    Thanks!