To podobne pytanie do [Ostrzeżenie FindBugs: Nieefektywne użycie iteratora keySet zamiast iteratora entrySet
Jednak tam staram się zrobić coś nieco innego. Mój obecny kod jest tutaj:
for (Double key2 : sortedPolygons.keySet()) {
if (sortedPolygons.get(key2).getExteriorRing().equals(hole)) {
sortedPolygons.remove(key2);
break;
}
}
Wykonanie czegoś takiego jak rozwiązanie w łączu nie działa. Oto implementacja wspomnianego rozwiązania:
for(Map.Entry<Double, Polygon> entry : sortedPolygons.entrySet()) {
if (entry.getValue().getExteriorRing().equals(hole)) {
.....
Problem polega na tym, że próbuję kasować wejście. Nie ma entry.remove()
. Jak mogę wymienić mój pierwszy blok kodu bez błędu FindBugs:
Nieefektywne użycie iteratora keySet zamiast iteratora entrySet ->
Ta metoda uzyskuje dostęp do wartości wpisu mapy,używając klucza, który był pobrane z iteratora keySet. Bardziej efektywne jest użycie iterator przy wpisie Ustaw mapę, aby uniknąć wyszukiwania Map.get (klucz).
Należy zauważyć, że podstawową strukturą jest TreeMap
i nie można tego zmienić.
Odpowiedzi:
5 dla odpowiedzi № 1Nie rozumiem twojego rozumowania: w pierwszym fragmencie używasz
sortedPolygons.remove(key2);
usunąć klucz. Nic nie stoi na przeszkodzie, aby zrobić to samo w drugim fragmencie:
sortedPolygons.remove(entry.getKey());
Niezależnie od tego, w jaki sposób iterujesz, doprowadzi to do ConcurrentModificationException
w każdym razie, ponieważ w większości kolekcji nie można go modyfikować podczas iteracji, z wyjątkiem iteratora.
Cytat z javadoc:
Iteratory zwrócone metodą iteracyjną metodykolekcje zwrócone przez wszystkie „metody widoku kolekcji” tej klasy są odporne na awarie: jeśli mapa jest modyfikowana strukturalnie w dowolnym momencie po utworzeniu iteratora, w jakikolwiek sposób, z wyjątkiem własnej metody usuwania iteratora, iterator zwróci ConcurrentModificationException.
Więc kod powinien być:
for (Iterator<Map.Entry<Double, Polygon>> it = sortedPolygons.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<Double, Polygon> entry = it.next();
if (entry.getValue().getExteriorRing().equals(hole)) {
it.remove();
// if you want to exit the loop as soon as you found a match:
break;
}
}
3 dla odpowiedzi № 2
Co powiesz na użycie iteratora entrySet () zgodnie z sugestią.
for(Iterator<Map.Entry<Double, Ploygon>> iter = sortedPolygons.entrySet().iterator();
iter.hasNext();) {
Map.Entry<Double, Ploygon> entry = iter.next();
if (condition)
iter.remove();
}
Jednak nie potrzebujesz klucza, aby po prostu iterować wartości
for(Iterator<Ploygon> iter = sortedPolygons.values().iterator();
iter.hasNext();) {
Ploygon ploygon = iter.next();
if (condition)
iter.remove();
}