public boolean hasNext() {
// TODO Auto-generated method stub
return current != null;
}
public T next() throws NoSuchElementException {
if (!hasNext())
throw new NoSuchElementException();
else
prev = current;
current = current.next;
return (T) prev.data;
}
//This is my linked list
f.add(132);
f.add(133);
//while loop I am using in regular main method to test
while(f.iterator().hasNext()){
System.out.println(f.iterator().next());
}
For some reason I just get an infinite loop here and I am not sure why. I ran this in my main method and it just kept printing 132, I am not sure what's wrong.
Get the iterator out of the loop. You are getting a new iterator every time the loop completes one circle. Thus just the first element is printed again and again.
Since the same element print again and again, there are 2 possibility could be happen.
The iterator is not moving and pointed to same element, even after you call next.
The linked-list is a circular one, iterator is automatically moving without call next. So iterator move to next Node (value = 133) and then calling next will move it to same element, since it is circular one.
I hope the problem is with the linked-list code. So give the linked-list code. It will help to find out the bug.
Related
In the Head First Design Patterns book, the authors describe using an iterator to traverse over composite data structures. They provide some sample code which, when executed, prints out a series of menu items stored within the composite. However, if you try to call the iterator more than once, it no longer works as expected and won't produce any results. The following code appears to be causing the problem:
public Iterator<MenuComponent> createIterator() {
if (iterator == null) {
iterator = new CompositeIterator(menuComponents.iterator());
}
return iterator;
}
In essence, they are creating a singleton iterator that cannot be reset for future iterations. Unfortunately, simply replacing this logic to return a new instance of the CompositeIterator also breaks the algorithm. An issue was raised on GitHub several years ago, although is yet to be resolved. Does anyone have any suggestions on how to overcome this issue?
As the linked issue says in the comments:
return iterator; // the `iterator' never resets to null once it's set.
We need to reset the iterator we are done with it, but not when the iterator still has elements left, because CompositeIterator depends on that.
One way to do this is to add another condition on which iterator is reset - when the iterator has no more elements:
public Iterator<MenuComponent> createIterator() {
if (iterator == null || !iterator.hasNext()) {
iterator = new CompositeIterator(menuComponents.iterator());
}
return iterator;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
So basically my code iterates through the list and the original method is supposed to return the linked list however it doesn't seem to be adding the nodes that I link in the recursive method and I'm confused as to why. Can anyone help me?
// Append MyStringBuilder2 b to the end of the current MyStringBuilder2, and
// return the current MyStringBuilder2. Be careful for special cases!
public MyStringBuilder2 append(MyStringBuilder2 b)
{
//Test if Invalid
if(b.firstC==null){
return this;
}
//Test if condition is met
else {
CNode lastNode =firstC;
recurseAppendBuild(lastNode, b);
return this;
}
}
private void recurseAppendBuild(CNode lastNode, MyStringBuilder2 BPoint) {
//Test if all nodes have been added
if(lastNode.next==null&&BPoint.firstC==null) {
System.out.println("finished");
}
//Tests if all nodes in the original linked list have been passed through
else if(lastNode.next==null) {
lastNode.next= new CNode(BPoint.firstC.data);
BPoint.firstC=BPoint.firstC.next;
recurseAppendBuild(lastNode.next, BPoint);
}
//Recurse until condition is met
else {
recurseAppendBuild(lastNode.next, BPoint);
}
}
```
Okay, your code needs some work. Let's look at your first method. I'm going to rewrite it.
public MyStringBuilder2 append(MyStringBuilder2 fromBuilder)
{
if (fromBuilder.firstC != null) {
recurseAppendBuild(fromBuilder.firstC);
}
return this;
}
I changed a number of things.
I used a more meaningful name on the argument. It's a good idea to give your variables meaningful names, not just 'b'. Note that I never use one-character names. If nothing else, it can be really hard to search on that. If you do "int i" and then search for i, you'll get a LOT of hits that aren't i at all.
This is a very trivial thing and doesn't affect the quality of your code.
In all cases, you always return yourself, so the return statement can be after the if-else structure, which is easier to see that it's the same.
That eliminates the top if-block entirely, so I reversed the logic.
And I changed the method signature of your recursive method, for reasons I'll describe below.
The end result is short and sweet and easily understood.
Now, let's look at your second method:
private void recurseAppendBuild(CNode lastNode, MyStringBuilder2 BPoint) {
//Test if all nodes have been added
if(lastNode.next==null&&BPoint.firstC==null) {
System.out.println("finished");
}
//Tests if all nodes in the original linked list have been passed through
else if(lastNode.next==null) {
lastNode.next= new CNode(BPoint.firstC.data);
BPoint.firstC=BPoint.firstC.next;
recurseAppendBuild(lastNode.next, BPoint);
}
//Recurse until condition is met
else {
recurseAppendBuild(lastNode.next, BPoint);
}
}
Your variable named BPoint breaks JAVA naming standards. It should start with a lower case letter.
If you pass in a MyStringBuilder2 as the second argument, then as you move things from BPoint to the end of your list and recurse, you have to remove them from BPoint, which is a pain in the ass. So instead, I didn't point to the wrapper. In my code above, I passed in the head of the list (fromBuilder.firstC).
You are finished when your list-to-append-from (BPoint) is empty, not when lastNode is null. Your first if is flawed.
You aren't recursively adding items. You're recursively looking for the end of the list. I don't think that's what you really want.
You're messing up the integrity of BPoint. You're making a copy of the nodes as you add them, but you're then dropping the old ones from BPoint but NOT maintaining lastC at all.
And you have a significant problem if your list starts as empty, as firstC and lastNode will both be empty.
So let's think about it this way. First, doing this recursively is silly, but that's the assignment, so we'll work with it.
A recursive definition is:
AppendedList = OriginalList + firstItem + Append Tail of List.
private void recurseAppendBuild(CNode headToAppend) {
if (headToAppend == NULL) {
// All done.
return;
}
CNode nodeToAppend = new CNode(headToAppend.data);
if (lastC == nullptr) {
// Original list is empty.
firstC = lastC = nodeToAppend;
else {
lastC.next = nodeToAppend;
lastC = nodeToAppend; // Point the tail at the new tail
}
// And here you recurse, always.
recurseAppendBuild(headToAppend.next);
}
Let's look at this.
I'm assuming you keep both a firstC and lastC in your builder. It would be deeply inefficient otherwise. So you only need to pass in the chain of nodes, not the surrounding wrapper.
By putting a null-check at the top of this method, you eliminate other null checks. Note -- this means we can eliminate the null check in the first method.
Create the new copy right away. That part's easy, right?
If lastC is null, you have an empty list, so you just point both front and back of the list to your new node.
Otherwise you point the old tail's next pointer to your new node and update the tail pointer to remain pointed at the tail.
Either way, you can safely recurse with the next object in the original list.
Advantages of this method, aside from working, is that you don't destroy the original list, and it's pretty clear to read.
For 2 days I'm pretty confused about .hasNext(); and next(); methods of Iteration interface especially in while loop. Let me give an example:
import java.util.*; // imported whole java.util package.
class Main {
public static void main(String[] args) {
ArrayList<String> cars = new ArrayList<String>(); // created ArrayList which name is cars.
cars.add("Volvo");
cars.add("Mercedes");
cars.add("BMW");
Iterator<String> x = cars.iterator();
while(x.hasNext()) {
System.out.print(x.next() + " "); // It prints Volvo Mercedes BMW
}
}
}
I understood that .hasNext(); is boolean and it returns true if iteration has elements. The .next(); method returns the next element. After first element Volvo, it gets back while(x.hasNext()) and entering the inside of loop again but where is the counter of this loop? I mean after printing Volvo how can it goes to the next element? It returns all element and if there is no more .hasNext(); returns false and code continues to next line is simple answer and correct but I want to understand it clearly.
Actually the iterator() Method Creates an iterator for all elements in your (let's say) Arraylist. Now in Your Code, the condition of while loop x.hasNext() checks whether the list contains an element or not, if yes it will return true else false.
Now x.next() point to First Element (Like of LinkedLists for example) in Your ArrayList and store that Object(Volvo in your case). When You Call this method it basically gives you reference of that object in List and the Iterator Moves to next element in the List. When Calling next() method the iterator(x in your case) returns the object and then moves to next Element (Mercedes in your case).
Now When you call next() method Again you will find Mercedes is returned. To know How it Works type System.out.println(x.next()) thrice instead of while loop u will understand that it moves to next location. If you type System.out.println(x.next()) fourth time it will give exception because there is no element in your list furthur more. Exception in thread "main" java.util.NoSuchElementException This is the Exception.
That's why hasNext() method is used as it checks whether an element is there or not.
you can Compare this to printing of linkedlist(Data structure if you know) where we make one object point to head node print it and move to next node. Same Case is here it returns current element(object) and moves to next element(object).
while is java-ese for: Keep doing this until a thing changes.
It's a bit like this common household task:
How to wash dishes
Check if there are still dirty dishes on the right side of the counter.
If there are some, do the dishwash thing: Pick up the nearest dirty dish, and wash it, then stow it away on the left side of the counter, and go back to the start of this algorithm.
Otherwise (there are no dirty dishes), you are done.
while (counterRightSide.hasItems()) {
Dish dirty = counterRightSide.fetch();
Dish clean = sink.clean(dirty);
counterLeftSide.stow(clean);
}
EDIT: I realize now that 'a kitchen counter' is an unfortunate example, given the homonym 'kitchen counter' and 'counter in code'. I'll use 'accumulator' instead of 'counter in code' to fix this confusion.
Note how there is no accumulator here either, and you aren't counting in your head when you wash the dishes either. You COULD first take inventory of the amount of dirty dishes you have (say, 15 dishes), and then write a protocol where you grab a dirty dish exactly 15 times before decreeing that you've done the job, but surely you realize that that's just one way to do it, and another is to just... check if there are any dirty dishes left every time you're done washing 1 dirty dish. Which is how the above code works.
Note that the action of 'fetching' an item from the right side of the kitchen counter changes properties of that kitchen counter. It now has one less item on it.
The same applies to iterators: Calling .next() on an iterator changes it in some form. After all, if you call next twice, the results of these calls are different. Contrast with invoking, say, someArrayList.get(5) a bunch of times in a row; that doesn't change the arraylist at all, and therefore you get the same thing back every time. next() is not like that.
So how DOES that work? Who counts this stuff?
Well, that's the neat thing about abstraction! A 'Collection' is something that can do a few things, such as 'it must be able to report to how how many items it holds', and, 'it must be able to festoon you an object that can be used to loop through each item that it holds'.
That's what an iterator is: An object that can do that.
So how does it work? Who knows! It doesn't matter! As long as you CAN do these things, you can be a collection, you are free to implement the task however you like.
Okay, but how does a common collection, like, say, ArrayList do this?
With a counter, of course. Here's the implementation:
public Iterator<T> iterator() {
return new Iterator<T>() {
int counter = 0; // here it is!
public boolean hasNext() {
return counter < size();
}
public int next() {
return get(counter++);
}
};
}
you're getting this object and referencing it in your code (your x variable), and that object has a field with a counter in it. You can't see it; it's private, and not actually in the Iterator type (Iterator is an interface; what you get is some unknown subtype of it, and that contains the counter variable). That's assuming you're getting an iterator by invoking .iterator() on an arraylist. If you invoke it on something else, there may or may not be a counter - as long as the iterator WORKS, it doesn't matter how it works, that's the beauty of interfaces.
A while loop checks the condition and when condition is true then executes the body of the loop and iterates itself,
while(condition){
//do something.
}
The hasNext() is a method from the Iterator interface which returns true if the "iteration" has more elements, if there are no more elements it returns fals and will no longer enter the body of the while loop:
while(x.hasNext){
//do something.
}
The next() method is a method from the Iterator interface and returns the next element of the iteration.
while(x.hasNext){
x.next();
}
I mean after printing Volvo how can it goes to the next element? It
returns all element and if there is no more .hasNext(); returns false
and code continues to next line is simple answer and correct but I
want to understand it clearly.
int cursor; // index of next element to return
//...
public boolean hasNext() {
return cursor != size;
}
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];
}
//...
Given above is how ArrayList#hasNext and and ArrayList#next have been implemented. The code is straight forward and easy to understand. You can check the full code by using a decompiler or here.
import java.util.ArrayDeque;
class Main {
public static void main(String[] args) {
ArrayDeque<Integer> arrayDeque = new ArrayDeque<>();
arrayDeque.push(10);
arrayDeque.push(11);
arrayDeque.push(15);
arrayDeque.push(20);
arrayDeque.push(200);
arrayDeque.add(700);
while (arrayDeque.peek() != null) {
System.out.println(arrayDeque.pop() + " ");
}
}
}
Good Day .. I have a question regarding the peek() method in ArrayDeque Class .. all the method will do is retrieve the head of the arrayDeque without removing it. so if that is the case how it's working perfectly without going for an infinite loop .. I mean who told the Method to look for the Next element after each complete loop.
There is no infinite loop because the condition in the whole loop will be false when the queue is empty.
while (arrayDeque.peek() != null)
When pop removes the last element, arrayDeque.peek() will return null and that's the end.
That is probably why I prefer to check for isEmpty().
This makes it easier to grasp that you need to pop elements off the queue or it will never go emtpy.
while (!arrayDeque.isEmpty()) { arrayDeque.pop(); }
I am working my way through a university practical on LinkedLists.
I am having difficulty understanding the add() method of an iterator traversing a LinkedList. Our lecturer has given us the code to implement this, so copying exactly from him:
public class LinkedList
{
public LinkedList() {
Node first = null;
}
class Node {
public Object data;
public Node next;
}
class LinkedListIterator implements ListIterator {
public LinkedListIterator() {
Node position = null;
Node previous = null;
}
public void add (Object element) {
if (position == null) {
addFirst(element);
current = first;
} else {
//1 Node newNode = new Node();
//2 newNode.data = element;
//3 newNode.next = current.next;
//4 current.next = newNode;
//5 current = newNode;
}
previous = current
}
Note: I have deliberately not encapsulated the variables and have cut out excess code to save space. I'm aware it doesn't compile, but my question is more conceptual.
In the add method:
The if statement simply detects if the iterator's position is null, in which case it adds the element to the start of the LinkedList and sets the iterators position to this newly created node.
The else statement is confusing me though:
Lines 1 & 2: A new node is created and its data is set to the element parameter.
Line 3, the next variable of this new node is set to the current node's next node i.e. it is set to whatever is after the position of the node the Iterator is pointing at.
Line 4, the "next" of the node the Iterator is currently pointing at is changed to the newNode (effectively completing the insertion of the new node between two existing nodes).
Line 5, the Iterator's position is set to point at the newNode.
After the else statement, the previous node that the Iterator was pointing at is set to the current node.
Herein lies the problem - doing that effectively syncs up the position and the previous position of the iterator. I checked this through the Eclipse debugger. This renders the previous useless. However, I'm aware that you can't reverse traverse a LinkedList using the standard iterator anyway.
When I comment this line out, nothing seems to change. Is this line simply unnecessary or does it have some function that I'm not actually realising? (Another reason I am asking is because the reverse of this appears in our notes for the remove() method, which again doesn't seem to have a purpose.
Edit: It appears this answer may be answered as my course develops. For now, I am moving the previous = current line to above the current = newNode line. This appears to keep all values separate.
The contract for ListIterator.add(Object) specifies that a subsequent call to next would be unaffected, and a subsequent call to previous would return the new element, that is the purpose of updating previous in the implementation of add.
Your professor probably gave you sample code that will be expanded upon later in the course. It looks like the sample code includes parts that would support a doubly linked list in future. Doubly linked list do allow reverse traversal of the list. See wikipedia for details.
On a completely unrelated topic; I applaud you for actually trying to understand and comprehend what was given to you instead of just plug-and-chugging to get the assignment done. That habit will serve you well in the future!
This looks like a bug to me. The previous = current assignment needs to happen before the current = newNode assignment. Then previous would refer to the old current, and the new current would be the newly created node.