For-loops allows to traverse a collection but when I tried to remove elements from a collection in For-loop it so happened that after deleting one element at particular location in collection, the positions of rest of the element in collection changed and when I again tried to delete another element in the same loop the element hasn't got deleted.
Firstly I thought that this problem may be solved by using size() method in for statement as
<!--[if gte vml 1]> <![endif]--><!--[if !vml]--><!--[endif]--><!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
because may be change in size of collection dynamically causing the problem. But I this solution didn't work.
I concluded from this that whenever we delete multiple elements in same for-loop some of the elements are missed or skipped due to shuffling of positions during the loop.
Also, there is a need of generic method to traverse and modify any form of collection. An iterator can be used for this purpose.
We need to see the element before we can decide that it is the one that should be removed from a collection. But in for-loop it is not necessary to lookup and then change. That is use of for-loop can make an attempt to change or remove an element without looking in it. So a tightly coupled mechanism for lookup and then change is needed. An iterator of collection Framework can be useful in solving this problem.
To find how for-loop caused problem and how iterator can solve this I have discussed about following in this BLOG:
1.Problem with For-Loop.
2.How Iterator are different from For-loop
3.Concept of Removing Elements using Iterator
4.For-Each Construct: The Enhanced For-Loop
5.Problem and Restrictions with the enhanced for loop
6.Example: JDOM multiple element deletion from ElementList problem
7.An Example of remove element using For-loop and Iterator
Problems with For-Loop
There are some basic disadvantages to using the traditional For-loop when we want to deal with more complex data structures. Fortunately, with the Collections framework, Java introduced the use of an Iterator. An Iterator allows us to move through the elements of a data structure with several advantages over the traditional For-loop.
First, with iterator we don't have to worry about explicitly managing the movement of the index. With the For-loop, we need to specify the upper and lower bounds, and if a mistake is made our program will terminate with an IndexOutOfBoundsException.
Second, we can use the Iterator interface to move over several datatypes, even through those that don't have a natural ordering to them. For example, we can use an Iterator to display the contents of a HashMap.
Finally, the Iterator allows us to remove elements from the underlying collection simply, again saving us from having to worry about recalculating the loop bounds or the new index position.
Iterators are different from For-loop
We can perform lookup directly using index of element independent of position change in For-loop using index++. While in Iterators the lookup and position change are tightly coupled. The only way to look up an element is to call next, and that lookup advances the position. Instead, we should think of Java iterators as being between elements. When we call next, the iterator jumps over the next element, and it returns a reference to the element that it just passed.
The For-loop is in many ways similar to a while loop in particular; it is pre-tested rather than post-tested, while in case of iterator it is post tested. It is most often used when a fixed number of iterations are required, with this number known in advance.
Concept of Removing Elements using Iterator
Problem: How to remove element from collection and to avoid unexpected results after deletion?
Solution: We can use iterator. Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.
An Iterator is an object that enables us to traverse through a collection, and to remove elements from the collection selectively, if desired. We get an Iterator for a collection by calling its iterator method.
The Iterator interface is:
The hasNext method returns true if the iteration has more elements, and the next method returns the next element in the iteration. The remove method removes from the underlying Collection the last element that was returned by next.
In many situations, that make sensewe need to see the element before we can decide that it is the one that should be removed. But if we want to remove an element in a particular position, we still need to skip past the element. For example, here is how you remove the first element in a collection of strings.
The remove method may be called only once per call to next and throws an exception if this rule is violated. There is a dependency between calls to the next and remove methods. It is illegal to call remove if it wasn't preceded by a call to next. If we try, an IllegalStateException is thrown.
If we want to remove two adjacent elements, we cannot simply call
it.remove();
it.remove(); // Error!
Instead, we must first call next to jump over the element to be removed.
it.remove();
it.next();
it.remove(); // Ok
Problem: Collections can be represented in many of forms. With such a variety of traversal mechanisms for different forms of collection, how can we hope to come up with a single generic method that will work for collections that are stored in wildly different forms?
Solution: This problem is solved by iterators. An iterator is an object that can be used to traverse a collection. Different types of collections have different types of iterators, but all iterators are used in the same way. An algorithm that uses an iterator to traverse a collection is generic, because the same technique can be applied to any type of collection.
Using iterators, we can write code for printing all the items in any collection. Suppose that coll is of type Collection. Then we can say:
Iterator iter = coll.iterator();
while ( iter.hasNext() ) {
Object item = iter.next();
System.out.println(item);
}
The same general form will work for other types of processing. For example, here is a subroutine that will remove all null values from any collection (as long as that collection supports removal of values):
void removeNullValues( Collection coll ) {
Iterator iter = coll.iterator():
while ( iter.hasNext() ) {
Object item = iter.next();
if (item == null)
iter.remove();
}
}
For-Each Construct : The Enhanced For-Loop
The for-each construct allows you to concisely traverse a collection or array using a for loop. The following code uses the for-each construct to print out each element of a collection on a separate line:
for (Object o : collection)
System.out.println(o);
Problem and Restrictions with the enhanced for loop
The syntax of the for(:) loop does not use an iterator for the collection.
CANNOT be used to remove elements from a collection. The 'for-each' loop hides the iterator, so you CANNOT call remove(). Therefore, the 'for-each' loop is not usable for filtering:
Example: JDOM element deletion from ElementList problem
JDOM element deletion from ElementList problemI have one XML file with multiple table elements like this. I am using Jdom for xml changes.
I want to delete the "table" elements which are having parentId="1″.
For deleting I am using the following code:
<!--[if gte vml 1]> <![endif]--><!--[if !vml]--><!--[endif]-->
tableList contains List of table Elementvalues.
But, I am getting the following result:
<!--[if gte vml 1]> <![endif]--><!--[if !vml]--><!--[endif]-->
Problem:Some of specified table elements are not deleted I think the problem is not with XML stuff but the loop iterating over a container is causing the problem. In loop, I am removing elements from the container, which in effect will shrink the size and hence will create possibilities to miss some locations.
Idiom: Do not remove items from a dynamic container while iterating over the same.
Solution: Use "Iterators" instead of the For-loop.
An Example of remove element using For-loop and Iterator
With all that data stored in our Array, we of course want some way to access that data. Using an Array inspector such as FetchItemAt() of course works, but there are times when we wish to walk our Array from one point to another, perhaps looking for a specific element or perhaps performing an operation on or with elements in the Array. This is where Iterators come in to play. An Iterator provides us with a means of sequentially traversing an Array. Again we could use a loop and FetchItemAt() to traverse our Array, but consider the following situation:
<!--[if gte vml 1]> <![endif]--><!--[if !vml]--><!--[endif]-->
What would happen in the above situation if targetData was found? It would of course be removed from the Array. After removing the item from the Array, the Array is now one less and numItems is no longer valid. When i == numItems, we could be in for some unexpected results! And if there happened to be more than one instance of targetData in the Array, we could be in for trouble a lot sooner. Instead, we can try using an Iterator:
<!--[if gte vml 1]> <![endif]--><!--[if !vml]--><!--[endif]-->
The two blocks of code perform the same function, but the latter version is savvier to the Array changing underneath it. The Iterators are not locked to certain numbers as the first example is, but rather to concepts such as "Next" and "Previous" to walk the Array. Additionally, an Array can have multiple Iterators.
No comments:
Post a Comment