ArthurMorgan
ArthurMorgan

Reputation: 75

Usage of Iteration's .hasNext(); and .next(); methods in Java

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.

Upvotes: 1

Views: 4247

Answers (4)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79015

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.

Upvotes: 1

Abhishek Agashe
Abhishek Agashe

Reputation: 52

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

Upvotes: 4

Jay_Pixel
Jay_Pixel

Reputation: 131

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

Upvotes: 2

rzwitserloot
rzwitserloot

Reputation: 102822

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.

Upvotes: 3

Related Questions