1. Java / Говнокод #4792

    +76

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    for (int j = 0; j < fieldsToRemove.size(); j++) {
    	if (fieldsToDelete.getField(j).getKind().equals("GroupField")) {
    		resFieldContr.remove(j--);
    	}
    }

    собственно цикл.
    нашел в рабочем проекте

    Запостил: tas, 30 Ноября 2010

    Комментарии (21) RSS

    • Может и работает, но в одной конструкции обращаться к одному списку тремя разными способами -- это нужно уметь.
      Ответить
    • да тут уабще не нужна J
      Ответить
    • модификация переменной цикла в разных местах не есть гуд.
      Ответить
      • Это нормальная практика, когда в цикле по условию удаляют элементы.
        for (int i = 0; i < somelist.size(); i++)
            if(todelete(somelist.get(i)))
                somelist.remove(i--);

        Можно
        for (int i = 0; i < somelist.size();)
            if(todelete(somelist.get(i)))
                somelist.remove(i);
            else
                i++;

        но это длиннее и непривычно.
        Ну и для длинных списков и большого количества удалений имеет смысл избавиться от O(N^2):
        int j = 0;
        for (int i = 0; i < somelist.size(); i++)
            if(!todelete(somelist.get(i)))
                somelist.set(j++, somelist.get(i));
        // дальше усекаем до размера j
        Ответить
        • --i++ и что в этом нормального
          с хвоста перебрать элементы религия не позволяет?
          Ответить
        • Второй вариант куда лучше, а длиннее всего на пару символов.
          К тому же, нормальная практика получать в цикле ссылку (указатель) на следующий элемент для обработки,
          не зависимо от того, удаляется текущий или нет.
          Я считаю, что изменение переменной цикла должно быть локализовано, так проще понять его назначение и совершить меньше ошибок.
          Ответить
          • Длиннее на две строки. В общем, скорее дело вкуса.
            Ответить
            • Напишите всё в одну строку - будет короче на четыре :)
              Ответить
    • А итератор никто не придумал?
      for (Iterator<BlaBlaBla> iterator = fieldsToRemove.iterator(); iterator.hasNext();) {
      	if (iterator.next().getKind().equals("GroupField")) {
      		iterator.remove();
      	}
      }
      Ответить
      • ВНЕЗАПНО, concurrent modification exception
        Ответить
        • Учим матчасть и идём запускать код руками.
          Итератор на то и имеет метод remove, чтобы можно было текущий элемент удалить.
          Ответить
          • Removes from the underlying collection the last element returned by the iterator (optional operation).
            Ответить
            • Назовите реализацию List'а, которая поддерживает метод remove, но не поддерживает remove у Iterator'a по этому List'у.
              Ответить
              • LinkedList
                Ответить
                • LinkedList использует в качестве итератора внутренний класс ListItr, в котором метод remove вполне себе определён и ConcurrentModificationException кинет только если этот список поменял в процессе итерации кто-либо другой.

                  И вообще, предлагаю запустить код.

                  public void testArrayListIterator() {
                          final List<String> list = new ArrayList<String>();
                          list.add("1");
                          list.add("2");
                          list.add("1");
                          for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
                              if ("1".equals(iterator.next())) {
                                  iterator.remove();
                              }
                          }
                          assertEquals(1, list.size());
                      }
                  
                      public void testLinkedListIterator() {
                          final List<String> list = new LinkedList<String>();
                          list.add("1");
                          list.add("2");
                          list.add("1");
                          for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
                              if ("1".equals(iterator.next())) {
                                  iterator.remove();
                              }
                          }
                          assertEquals(1, list.size());
                      }
                  Ответить
                  • да, Вы оказались правы.
                    Удалять из итератора можно. Нельзя удалять напрямую из коллекции, по которой создан итератор.

                    я пальцем в лужу, бывает)
                    Ответить

    Добавить комментарий