Как изменить объекты в списке<? расширяет MyObject> во время итерации?

Я пытаюсь изменить поле в выбранных объектах в списке, но я не могу найти способ сделать это, используя простой итератор, потому что он не имеет set() метод.

Я пытался использовать ArrayListIterator, который обеспечивает set() метод, но это вызывает исключение приведения. Есть ли способ обойти это?

   Iterator it = topContainer.subList.iterator();
   while (it.hasNext()) {
      MyObject curObj = (MyObject) it.next();
      if ( !curObj.getLabel().contains("/") ) {
           String newLabel = curObj.getLabel() + "/";
           curObj.setLabel(newLabel);
           ((ArrayListIterator) it).set(curObj)
       }
    }

Я ожидаю, что исходный текущий объект в списке будет установлен без инцидентов, но вместо этого я получаю это исключение:

java.util.ArrayList $ itr нельзя преобразовать в org.apache.commons.collections.iterators.ArrayListIterator

Как правильно выполнить то, что я хотел бы сделать?

3 ответа

Решение

Вам не нужно звонить set совсем. Вы можете просто позвонить setLabel на curObj:

// please, don't use raw types!
Iterator<? extends MyObject> it = topContainer.subList.iterator();
while (it.hasNext()) {
   MyObject curObj = it.next();
   if ( !curObj.getLabel().contains("/") ) {
       String newLabel = curObj.getLabel() + "/";
       curObj.setLabel(newLabel);
   }
}

Правильный путь будет следующим (работает не для версий Java ниже 1.5):

for(MyObject curObj : topContainer.subList){
    if (!curObj.getLabel().contains("/")) {
       String newLabel = curObj.getLabel() + "/";
       curObj.setLabel(newLabel);
    }
}

Это расширенный цикл for, и он тоже вызывает итератор, но вы его не видите.

Также установка объекта через итератор не требуется, так как вы работаете со ссылками на ObjectВ Java, когда вы редактируете объект, все, у кого есть указатель на этот объект, тоже увидят это изменение. Более подробно вы можете прочитать этот замечательный пост: Java "передается по ссылке" или "передается по значению"?

Если вы не можете использовать Java 5, значит, вы упускаете большие возможности. Текущая версия Java - 11. Таким образом, вы должны действительно, действительно, действительно, обновить свой JDK

Вы просто должны установить метку. В JAVA 11 вы можете использовать потоки. это делает ваш код более читабельным.

List<MyObject> list = topContainer.subList;
list
    .stream()
    .filter(Predicate.not(e->e.getLabel().contains("/")))
    .forEach(e->e.setLabel(e.getLabel()+"/"));

В Java 8 вы можете использовать

(!e->e.getLabel().contains("/"))

вместо

Predicate.not(e->e.getLabel().contains("/")

Другие вопросы по тегам