3

我目前有以下代码

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();
        }
    }
}

但是,我在线上遇到 NoSuchElementException 崩溃

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

使用 isEmpty() 方法和调用 hasNext() 调用有很大区别吗?我知道 hashmaps 没有 hasNext() 调用,所以我做了以下操作:

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();
        }
    }
}

显然,我知道我应该只运行应用程序并查看它是否崩溃,但问题是很难重现该问题。

谢谢!

4

6 回答 6

6

可见Tiles.isEmpty()

只是检查地图是否为空(或)它是否有任何元素。

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

从迭代器中检索下一个元素。

在迭代器上做之前你需要做hasNext()检查。next()

hasNext() javadoc

如果迭代有更多元素,则返回 true。(换句话说,如果 next 将返回一个元素而不是抛出异常,则返回 true。)

所以,如果没有可用的元素并且调用next()迭代器将返回NoSuchElementException

最重要的是,我认为你真的不想做空支票

while (!visibleTiles.isEmpty())) {
....
}
于 2012-10-24T16:12:41.503 回答
1

while (visibleTiles.keySet().iterator().hasNext())Iterator每次调用时都会创建一个新的*。如果visibleTiles不为空,则始终为 true,因为永远不会调用相应迭代器的 next 方法并且内部指针永远不会前进。

迭代器应该像这样使用:

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

*这里的重点是可能有多个迭代器同时引用同一个集合。每个迭代器都有自己的内部状态存储(不一定显式)最后返回的元素以及next()调用下一个应返回的元素。这可能很有用,例如,对集合中的所有元素对执行一些操作,其中需要两个迭代器。

于 2012-10-24T16:27:47.733 回答
1

您可以使用 com.google.common.collect.Iterables 类对 Iterable 值进行空检查。

Iterables.isEmpty(yourIterable)
于 2017-11-01T08:00:56.183 回答
0

修复 while 条件应该可以解决问题

通过在前面添加 not(!) 将条件更改为检查非空:

   while (!visibleTiles.isEmpty())) {

编辑:示例代码:

    HashMap<String, Object> visibleTiles = new HashMap<String, Object>();
    visibleTiles.put("abc", new Object());
    visibleTiles.put("xyz", new Object());
    visibleTiles.put("def", new Object());
    String tile = null;
    while (!visibleTiles.isEmpty()) {
        tile = visibleTiles.keySet().iterator().next();
        if (tile != null){
            Object bitmap = visibleTiles.remove(tile);
            if(bitmap != null){ //safe to recycle if tile cache is not actively holding it
                System.out.println("Recycle");
            }
        }
    }
于 2012-10-24T16:28:32.137 回答
0

多亏了有关效率的良好信息,我通过删除 isEmpty 调用,用原始帖子中的代码修复了 no such element 异常。当您在同一代码区域中调用 next 时,您通常希望使用 hasNext 。

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();
            }
        }
    }
于 2012-10-25T17:38:25.393 回答
0

这与您提出的问题(已经回答)无关,而只是作为文档的附注

请注意,不能保证迭代器的快速失败行为,因为一般来说,在存在不同步的并发修改的情况下,不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖于这个异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。

您可以避免在键集迭代器上删除(最终从地图中删除条目),而不是在地图本身上进行删除(在迭代键集时从外部修改地图)。

看起来易受攻击的代码部分:

tile = visibleTiles.keySet().iterator().next();
if (tile != null){
    bitmap = visibleTiles.remove(tile);

例子:

以下导致ConcurrentModificationException

Map<String, String> map = new HashMap<String, String>();         
map.put("1", "1");
map.put("2", "1");
map.put("3", "1");
Iterator<String> it = map.keySet().iterator();
while(it.hasNext()) {
    if(it.next().equals("2")) {
         map.remove("2");
    }
}

而以下从地图中删除条目:

Map<String, String> map = new HashMap<String, String>();         
map.put("1", "1");
map.put("2", "1");
map.put("3", "1");
Iterator<String> it = map.keySet().iterator();

while(it.hasNext()) {

    String key = it.next();

    if(key != null) {

         String value = map.get(key); // you have the value and
         it.remove(); //you are modifying the map only through the iterator itself

         //... do stuffs with the value
    }
}
于 2012-10-24T16:39:19.663 回答