• Post Reply Bookmark Topic Watch Topic
  • New Topic

ListIterator  RSS feed

 
Vineeth Menon
Ranch Hand
Posts: 79
Eclipse IDE Java Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried searching for this and I could not find the answer, could someone please tell me why the ListIterator is not working when I try the "previous" method...here is the code



The above code is working perfectly, but in the while loop when I change from hasNext() to hasPrevious() and in the next line when I say list.previous() is does not work



I know it must some silly mistake, but any help would be appreciated...

Thanks
Vinnie
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It works perfectly. It goes through all the previous elements in the list. Of which there are precisely zero, for the same reason there are zero next elements when you're at the end of the list.

When you call listIterator(), the new iterator as at the beginning of the list, right before the first element. So as long as the list it not empty, there is a next element. However, when you're at the beginning of the list, there is no previous element.
 
Vineeth Menon
Ranch Hand
Posts: 79
Eclipse IDE Java Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok Jeff, so use a ListIterator to iterate over a list of data and then if I want to print it backwards or add something, use the previous method or the set method to add. So by this way, there is data in the ListIterator Object to print the previous values. When I did it before there was nothing to print backwards... am I right?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Vineeth Menon wrote:Ok Jeff, so use a ListIterator to iterate over a list of data


If all you want to do is iterate forward, a plain old Iterator is fine.

and then if I want to print it backwards or add something, use the previous method or the set method to add.


If you want to print the list backward, yes, you could go to the end with a ListIterator and then work your way backward. That's not the only way to do it, and it's probably not what ListIterator is usually used for.

If you want to modify the list during iteration, the only correct way to do so is through the iterator. Iterator.remove(), ListIterator.add() or remove() are fine for that. List.set() is not a valid option to modify a list while you have an active iterator.

So by this way, there is data in the ListIterator Object to print the previous values. When I did it before there was nothing to print backwards... am I right?


"Data to print the previous values"? No, not as such. ListIterator gives you the ability to move backward as well as forward--that is, to access the previous values during iteration. It's not specifically meant for printing the list backward, but you can use it for that. It's also not the only way to print a list backward.
 
Vineeth Menon
Ranch Hand
Posts: 79
Eclipse IDE Java Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
HI Jeff,

Thanks for the detailed explanation. I was going through the Iterator interface and exploring all the methods that are there in Iterator and ListIterator interfaces. But I did see an example on the web were set method was being used while a ListIterator was active. But I will keep in mind that data modification should be done through the remove or add method.

Again thanks a lot for clearing my doubts mate...
This is why I love Code Ranch.
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jeff Verdegan wrote:If you want to modify the list during iteration, the only correct way to do so is through the iterator. Iterator.remove(), ListIterator.add() or remove() are fine for that. List.set() is not a valid option to modify a list while you have an active iterator.

Um, to shift the emphasis a bit and fix an error... Iterator.remove(), ListIterator.add(), ListIterator.remove(), and ListIterator.set() are all fine for modifying the list during iteration. List.add(), List.remove(), or almost any other mutator methods on the List, are not valid options. The List.set() methods are actually OK, because they do not structurally modify the list. But you may be better off ignoring that, and sticking with the rule that you simply do not modify a list through the iterator and the list at the same time.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, my mistake. I didn't even realize ListIterator has a set() method.

@Vineeth, when I said you can't use set(), I meant you shouldn't use List's set() method (or any List method) to change the list. I didn't realize ListIterator has its own set() method. Since it does, that one is fine to use.

Sorry for any confusion.
 
Vineeth Menon
Ranch Hand
Posts: 79
Eclipse IDE Java Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike Simmons wrote:The List.set() methods are actually OK, because they do not structurally modify the list. But you may be better off ignoring that, and sticking with the rule that you simply do not modify a list through the iterator and the list at the same time.


Did not really understand that part especially where list is getting structurally modified Mike, can you please explain???
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Vineeth Menon wrote:
Mike Simmons wrote:The List.set() methods are actually OK, because they do not structurally modify the list. But you may be better off ignoring that, and sticking with the rule that you simply do not modify a list through the iterator and the list at the same time.


Did not really understand that part especially where list is getting structurally modified Mike, can you please explain???


Structural modification is things like adding to the list, removing from the list, possibly changing the order in a LinkedList (depending on how it's done). When we do one of these things while there's an active Iterator, it can cause unexpected behavior, such as causing the Iterator to skip an item, or return the same item twice, or give an exception for trying to access an element that's no longer there. That's why we only do them through Iterator calls, not List calls--so that the Iterator will know what has been done and adjust its state accordingly.

In the case of List.set(), it doesn't have to structurally change the list (although it's possible that some implementations could do so in a way that would mess up an ongoing iteration). The size of the list doesn't change, and if it's done carefully, none of the lists node pointers change which node they're pointing to. All that changes is the contents of existing nodes.
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[composed before I saw Jeff's reply above, but it seems to supplement Jeff's comments anyway, so I'll leave it...]

Vineeth Menon wrote:
Mike Simmons wrote:The List.set() methods are actually OK, because they do not structurally modify the list. But you may be better off ignoring that, and sticking with the rule that you simply do not modify a list through the iterator and the list at the same time.


Did not really understand that part especially where list is getting structurally modified Mike, can you please explain???

The rules for this stuff actually depend on the underlying List implementation; some implementations may not throw ConcurrentModificationException at all. But ArrayList and Linked list do, and their APIs contain the following text:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.)

You could also investigate the source code for these classes, and see that ArrayList.add() and remove() each call modCount++, while set() does not. This is used by ArrayList.Itr.checkForComodification() and LinkedList.ListItr.checkForComodification(), which is the thing that throws ConcurrentModificationException when these lists are used incorrectly.

So, if you know that you're using an ArrayList or LinkedList, you can safely use List.set() rather than ListIterator.set(). Though there's not much point, really - just using the ListIterator methods is safest, if you're using an iterator at all.
 
Vineeth Menon
Ranch Hand
Posts: 79
Eclipse IDE Java Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@ Jeff and @ Mike...

So if I were to use ListIterator calls like this



would this be the correct way???
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, that looks correct.
 
Vineeth Menon
Ranch Hand
Posts: 79
Eclipse IDE Java Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for all the help mate...
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!