Как изменить объекты в списке<? расширяет 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("/")