Introspective
Introspective

Reputation: 736

How to modify objects in a List<? extends MyObject> while iterating?

I am trying to modify a field in select objects in a List but I am unable to find a way to do so, using plain Iterator because it has no set() method.

I tried using ArrayListIterator that provides a set() method, but this throws a casting exception. Is there way to workaround this?

   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)
       }
    }

I expect the original current object in the list to be set without incident, but instead I am getting this exception:

java.util.ArrayList$itr cannot be cast to org.apache.commons.collections.iterators.ArrayListIterator

What is the proper way of accomplishing what I would like to do?

Upvotes: 1

Views: 414

Answers (3)

Khalid Shah
Khalid Shah

Reputation: 3232

you just have to set the label. In JAVA 11 you can use streams. it makes your code more readable.

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

In java 8 you can use

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

instead of

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

Upvotes: 2

Lino
Lino

Reputation: 19926

The correct way would be following (works not for java versions below 1.5):

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

This is an enhanced for-loop, and it does call the iterator too, but you can't see it.

Also setting the object via the iterator is not needed, as you're working with references to Objects in Java, when you edit an object, everyone that has a pointer to that object, will see the change too. For more you can read this great post: Is Java “pass-by-reference” or “pass-by-value”?

If you can't use Java 5, then you're missing out big time. The current java version is 11. So you should really, really, really, upgrade your JDK

Upvotes: 3

Sweeper
Sweeper

Reputation: 271555

You do not need to call set at all. You can just call setLabel on 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);
   }
}

Upvotes: 4

Related Questions