我目前有以下代码
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();
}
}
}
显然,我知道我应该运行应用程序并查看它是否崩溃,但问题是重现问题很困难。
谢谢!
答案 0 :(得分:4)
visibleTiles.isEmpty()
只检查地图是否为空(或)是否有任何元素。
ile = visibleTiles.keySet().iterator().next();
从迭代器中检索下一个元素。
在迭代器上执行hasNext()
之前,您需要进行next()
检查。
hasNext()
javadoc说
如果迭代有更多元素,则返回true。 (换一种说法, 如果next会返回一个元素而不是抛出一个元素,则返回true 异常。)
所以,如果没有可用的元素,并且在迭代器上调用next()
将返回NoSuchElementException
。
除此之外,我认为你真的不想空检查
while (!visibleTiles.isEmpty())) {
....
}
答案 1 :(得分:1)
while (visibleTiles.keySet().iterator().hasNext())
都会创建一个新的Iterator
。如果visibleTiles
不为空,则总是如此,因为从不调用相应迭代器的下一个方法,并且内部指针永远不会前进。
迭代器应该像这样使用:
Iterator<TileType> tileIt = visibleTiles.keySet().iterator();
while (tileIt.hasNext()) {
TileType tile = tileIt.next();
// ...
}
*这里的要点是可能有几个迭代器同时引用同一个集合。每个迭代器都有自己的内部状态存储(不一定是显式的)最后返回的元素,然后由next()
调用返回。这可能很有用,例如,对集合中的所有元素对执行一些操作,其中需要两个迭代器。
答案 2 :(得分:1)
您可以使用com.google.common.collect.Iterables类对Iterable值进行空检查。
Iterables.isEmpty(yourIterable)
答案 3 :(得分:0)
在条件解决问题时进行修复。
通过在前面添加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");
}
}
}
答案 4 :(得分:0)
这与您提出的问题无关(已经回答),但仅作为docs
的旁注请注意,迭代器的快速失败行为无法得到保证,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬性保证。失败快速迭代器会尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应该仅用于检测错误。
你可以避免你可以在keyset迭代器上删除(最终从地图中删除条目),而不是在地图上进行删除(在迭代键集时从外部修改地图)。
代码中看起来容易受到攻击的部分:
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
}
}
答案 5 :(得分:0)
由于有关效率的良好信息,我通过删除isEmpty调用修复了原始帖子中的代码没有这样的元素异常。看起来你通常想在同一个代码区域中调用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();
}
}
}