Reverse Ordered list using Previous Iterator - java

I want to start at the end of the list and iterate it using ListIterators previous method
public void add(E obj) {
ListIterator <E> iter = theList.listIterator();
while (iter.hasNext()) {
if (obj.compareTo(iter.next()) < 0) {
iter.previous();
iter.add(obj);
return;
}
}
iter.add(obj);
}
Every time I run my test class it iterators from the beginning.

to get iterator in reverse order use method list.listIterator(int index)
this method will return iterator from specified position,
you should put size of list means last element index.
after that you can use hasPrevious() and previous() method.
this will work,
// declare arraylist
ArrayList<...> a = new ArrayList<...>();
// Add elements to list.
// Generate an iterator. Start just after the last element.
ListIterator li = a.listIterator(a.size());
// Iterate in reverse.
while(li.hasPrevious()) {
System.out.println(li.previous());
}

ListIterator, like all Iterators, always start at the beginning. The previous method allows for less constrained movement, but it still starts at the beginning. You overall intent is unclear, so it's possible you're coming at this the wrong way, but the most straightforward way for you would be to reorder the list first and then do your iteration.
UPDATE Nevermind, Rajj has it.

Related

Changing list while iterating over it and iterating over new elements

i was wondering if this is possible, and if it is, how can i do it?
Basically what i saw, and think is problem is that cursor of iterator is moving when I am using add function(I dont understand iteration perfectly so I dont know if this is problem).The problem happens when i remove one element and then add two more(that is specific case where i found a problem).
My code is something like this:
List<String> list =new ArrayList<>();
for (ListIterator<String> iterator = list.listIterator(); iterator.hasNext();)
//here i am adding and removing elements
ListIterator According to JLS
An iterator for lists that allows the programmer to traverse the list
in either direction, modify the list during iteration, and obtain the
iterator's current position in the list. A ListIterator has no current
element; its cursor position always lies between the element that
would be returned by a call to previous() and the element that would
be returned by a call to next(). An iterator for a list of length n
has n+1 possible cursor positions, as illustrated by the carets (^)
below:
You can use the add(), remove() method to make the modification in iterator and same will be reflected in the list reference.
Remove as per JLS
Removes from the list the last element that was returned by next() or
previous() (optional operation). This call can only be made once per
call to next or previous. It can be made only if add(E) has not been
called after the last call to next or previous.
So if you use remove twice without calling next() or previous() it will throw java.lang.IllegalStateException
I modified your code to test add() and remove()
public static void main(String[] args) {
List<String> list =new ArrayList<>();
list.add("55");
list.add("155");
list.add("255");
for (ListIterator<String> iterator = list.listIterator(); iterator.hasNext();){
System.out.println(list.size());
iterator.add("88");
System.out.println(list.size());
iterator.next();
System.out.println(list.size());
iterator.remove();
System.out.println("first remove done");
iterator.remove(); // will throw exception if previous or next is not called
}
System.out.println(list);
}

How for-each loop knows where to start?

Iterator is guaranteed to have the following methods:
hasNext()
next()
remove (optional)
When for-each loop iterates through iterable class objects, how does it know what object to start with? The above methods provide clear path forward, but what points to the starting element?
For-each guarantees to iterate through all relevant objects. Depending on a class and its next() implementation it could be vitally important where to start (consider forward linked list or any other implementation that has a root element).
How does it work?
If my question does not make sense please explain why.
From the spec:
What's officially called the enhanced for statement (for(E e: Iterable<E> iterable)) is translated by the compiler into the equivalent of the following code:
E e;
for(Iterator<E> it = iterable.iterator(); it.hasNext(); ) {
e = it.next();
// contents of your for loop
}
The behavior of the loop is exactly as if you'd written it with an explicit Iterator, so the "starting point" of the enhanced for loop is wherever iterable.iterator() would have started anyway.
You might want to look at ArrayList's implementation of an Iterator, the Itr inner class.
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
#SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
...
}
cursor gets initialized to 0 by default. You use cursor to access the elements in the ArrayList object's backing array (it's an inner class, it has access to that field).
Similar logic applies for other implementations of Iterator. It always depends on the underlying data structure. As another example, a Set is not supposed to have an ordering, but it does implement Iterator. A decision has to be made as to where the iterator starts.
foreach is a shorthand for for loop starting from first till last.
This all depends on your collection.
If your collection is a List (ArrayList or LinkedList usually), then the iterator will go in list order according to how they were inserted.
If it is a Map or Set, it is very hard to predict the ordering of its members. If you are using a Map or Set, you should not count on any sort of predictable ordering, in fact, because it doesn't match those collections' purposes. However, LinkedHashMap or LinkedHashSet can be used if you need a specific order but also need the functionality of a Map or Set.

Can I subclass "standard" arraylist iterator?

I need to iterate all the elements of ArrayList except the last one. So I want to create such iterator. But I don't what to implement the whole iterator, I need to override only the hasNext() method, so I would like to subclass a "standard" iterator. Is there any way to do that?
I think the better way to do that rather than overriding the default iterator is to iterate the ArrayList on your own. An ArrayListhas a couple of method defined that can help you accomplish the task: get(int) and size().
Everything you have to do is to get the total number of elements in the ArrayList(with size()) and then loop through the elements accessing each element directly in each iteration using the get() method. Your code would look something like this:
for(int i = 0; i < myList.size() - 1; i++){
element = myList.get(i);
//do something
}
Now with this principle in mind, you may create your own class to iterate the ArrayList.
It would be odd to modify the iterator to perform this traversal. The obvious thing to do is to write the "algorithm" as you want it:
public static <T> void eachExceptLast(List<? extends T> list, Operation<T> op) {
Iterator<T> iter = list.iterator();
if (!iter.hasNext()) {
return;
}
T item = iter.next();
while (iter.hasNext()) {
op.run(item);
item = iter.next();
}
}
(Or use an index assuming a RandomAccess list.)
However, there's a much better way of doing this. list.subList(0, list.size()-1) (for a non-empty list) will return a view of the original list less the last element. It doesn't do a copy, and you can even use Iterator.remove.
You can create a class that implements either the Iterator or ListIterator interfaces and then override the hasNext() method .

Creating a sorted linked list class

I'm trying to create a SortedLinkedList class which extends LinkedList. This class is supposed to add items to a SortedLinkedList and have them sorted.
I'm trying to override the boolean add(E obj) method in order to add items in sorted order.
On a Stackoverflow question I found the following method of overriding add(E obj):
public boolean add(E obj) {
int index = 0;
for( ; index<size() ; index++){
E object= get(index);
if(obj.compareTo(object) < 0){
break;
}
}
add(index, obj);
return true;
};
I understand how this method works, however I've read that using a ListIterator would be more efficient than using get(index). I've been trying to use a ListIterator but I can't seem to get everything to work correctly.
This is how far I got with using the Listiterator, I'm sure there is something wrong with it but I can't seem to figure it out:
public boolean add(E obj)
{
add(size(), obj);
ListIterator<E> iterator = listIterator();
while(iterator.hasNext())
{
E object = iterator.next();
if(obj.compareTo(object)<0)
{
//do something;
}
}
return true;
}
Any advice on how I can sort the list using the iterator?
Don't think about sorting the list using the iterator. Think about inserting a new element into an already-sorted list using the iterator.
Your list will start off empty. When you add the first element, you will have a list of one element, which is, by definition, sorted. If you make sure that you always add subsequent elements in the right place, then the list will stay sorted!
This is exactly what the code that uses get does, but as you quite rightly say, that is not efficient for linked lists. What you need to do is reproduce that algorithm using the iterator.
Hint: a list iterator lets you add an element at the current position.

Iterator has .next() - is there a way to get the previous element instead of the next one?

I have an Iterator that I use on a HashMap, and I save and load the iterator.
is there a way to get the previous key in the HashMap with Iterator? (java.util.Iterator)
Update
I save it as an attribute in a Red5 connection and then load it back to continue working where i stopped.
Another update
I'm iterating through the keyset of the HashMap
You can use ListIterator instead of Iterator.
ListIterator has previous() and hasPrevious() methods.
Not directly, as others pointed out, but if you e.g. need to access one previous element you could easily save that in a separate variable.
T previous = null;
for (Iterator<T> i = map.keySet().iterator(); i.hasNext();) {
T element = i.next();
// Do something with "element" and "previous" (if not null)
previous = element;
}
It sounds like you want the array semantics more akin to a ListIterator rather than those provided by the Iterator interface. The easiest way to acquire such a thing is likely to construct a list ( from the key-set (LinkedList<K> keyList = new LinkedList<K>(map.keySet())), then use a ListIterator manually instead of a regular Iterator or foreach.
For very simple cases of needing to remember consecutive items, the simplest way to handle this is to store the previous Key in a local variable and update it at the end of the loop.
No, an Iterator<E> defines only 3 methods:
boolean hasNext()
E next()
void remove()
You can of course implement your own iterator.
As others have said, you only access an element using next(). However it's sort of a matter of terminology. Once you call next() this is the current element.
Unless the problem is you need to see two consecutive items in the collection each iteration, in which case a simple variable would seem easiest.
Although Set doesn't provide a method for a reverse iterator, Deque does. You can use descendingIterator() for an iterator in reverse order and iterator(), for an iterator in forwards order.
(You can create a Deque from a Set via Deque<T> deque = new LinkedList<T>(set), where set is your Set and T the generic type you're using.)
Ultimately Iterators are not fully suited for your task.
Why not create a List from your Set (via, eg, List list = new LinkedList(set)) and iterate by using a standard indexed for-loop? That way you know the previous element is at i - 1.
using iterator, No you dont have an option to get a previous key value. it has only hasNext() and next() methods.
No, you can't. The Iterator interface has no method to get the previous element.
But what you can do is - a little bit rubbish- creating a List<Entry<Integer, YourObjectType>> where the Integer-value represents the hash-code of the key-object. Then you can do something like this:
for (int i = 0; i < list.size(); i++)
{
YourObjectType current = list.get(i).getValue();
YourObjectType previous = (i == 0 ? null : list.get(i - 1).getValue());
// Do whatever you want
}
I know this is very rubbish, but it is possible
Make your own Iterator:
public class EnhancedIterator<E> implements Iterator<E>{
private List<E> list;
private int indexSelected=-1;
public EnhancedIterator(List<E> list){
this.list=list;
}
#Override
public boolean hasNext() {
return indexSelected<list.size()-1;
}
#Override
public E next() {
indexSelected++;
return current();
}
#Override
public void remove() {
list.remove(indexSelected);
}
public void remove(int i){
list.remove(i);
if(i<indexSelected){
indexSelected--;
}
}
public E previous(){
indexSelected--;
return current();
}
public E current(){
return list.get(indexSelected);
}
public E get(int i){
return list.get(i);
}
}

Categories