Предупреждение FindBugs: неэффективное использование итератора keySet

1

Этот аналогичный вопрос для [ FindBugs warning: Неэффективное использование итератора keySet вместо itStation entrySet

Тем не менее, я пытаюсь сделать что-то совсем другое. Мой текущий код находится здесь:

for (Double key2 : sortedPolygons.keySet()) {
    if (sortedPolygons.get(key2).getExteriorRing().equals(hole)) {
        sortedPolygons.remove(key2);
        break;
    }
}

Выполнение чего-то вроде решения в ссылке не работает. Вот реализация этого решения:

for(Map.Entry<Double, Polygon> entry : sortedPolygons.entrySet()) {
    if (entry.getValue().getExteriorRing().equals(hole)) {
         .....

Проблема здесь в том, что я пытаюсь удалить запись. Нет entry.remove(). Как я могу заменить свой первый блок кода без ошибки FindBugs:

Неэффективное использование итератора keySet вместо итератора entrySet ->

Этот метод позволяет получить доступ к значению записи в карте, используя ключ, который был получен из итератора keySet. Эффективнее использовать итератор на entrySet карты, чтобы избежать поиска Map.get(key).

Следует отметить, что базовая структура - TreeMap, и ее нельзя изменить.

Теги:
iterator
treemap
sonarqube
findbugs

2 ответа

5
Лучший ответ

Я не понимаю ваших рассуждений: в первом фрагменте вы используете

sortedPolygons.remove(key2);

для удаления ключа. Ничто не мешает вам сделать то же самое во втором фрагменте:

sortedPolygons.remove(entry.getKey());

Независимо от того, как вы итерации, это приведет к ConcurrentModificationException любом случае, потому что для большинства коллекций вы не можете изменять его во время итерации на нем, за исключением использования его итератора.

Цитата из javadoc:

Итераторы, возвращаемые методом итератора коллекций, возвращаемых всеми этими методами "методы просмотра коллекции", являются неустойчивыми: если карта структурно модифицирована в любое время после создания итератора, любым способом, кроме как через собственный итератор, удалить метод, итератор будет вызывать исключение ConcurrentModificationException.

Таким образом, код должен быть:

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;
    }
}
  • 1
    Примечание: ключ на самом деле не нужен (см. Мой ответ)
  • 1
    @PeterLawrey: согласился. +1 к вашему ответу. Я оставлю свой ответ как есть, чтобы показать оператору, как перебирать записи, на тот случай, если ему понадобится ключ в будущем.
Показать ещё 4 комментария
3

Как насчет того, как вы используете итератор entrySet(), как это было предложено.

for(Iterator<Map.Entry<Double, Ploygon>> iter = sortedPolygons.entrySet().iterator(); 
         iter.hasNext();) {
    Map.Entry<Double, Ploygon> entry = iter.next();

    if (condition)
        iter.remove();
}

Однако вам не нужен ключ, поэтому вы можете просто перебирать значения

for(Iterator<Ploygon> iter = sortedPolygons.values().iterator(); 
         iter.hasNext();) {
    Ploygon ploygon = iter.next();

    if (condition)
        iter.remove();
}
  • 0
    Ах. Понимаю. Ключ используется только для итерации значений. Так что просто итерируйте значения .
  • 1
    +1 за напоминание, что вы можете удалить полную запись, используя значение итератора.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню