views:

97

answers:

3

What I am trying to do is save a Move objects into a Vector called topMoves. There will be many Move objects which is why I create the object within the loop.

The pastPriceMap stores prices for stocks at some past time (in this case one minute ago). The currPriceMap stores price for stocks some time within the last second.

I get the following exception:

Exception in thread "Timer-0" java.util.NoSuchElementException

This is the line that is causing the problem: amove.setInitPrice(pastPriceMap.get(iter.next()));

The code snippet is below. When I do the System.out.println statements I get the expected output:

Iterator<String> iter = sortedTopCodes.iterator();

while(iter.hasNext()){

 System.out.println(currPriceMap.get(iter.next()));
 System.out.println(pastPriceMap.get(iter.next()));

        Move amove = new Move();
 amove.setSecCode(iter.next());
 amove.setPrice(currPriceMap.get(iter.next()));
 amove.setInitPrice(pastPriceMap.get(iter.next()));
 topMoves.add(amove);
}

    return topMoves;


The Move class looks like this:

private String secCode;
private double price;
private double initPrice;

public String getSecCode() {
 return secCode;
}
public void setSecCode(String secCode) {
 this.secCode = secCode;
}
public double getPrice() {
 return price;
}
public void setPrice(double price) {
 this.price = price;
}

public double getInitPrice() {
 return initPrice;
}
public void setInitPrice(double lastPrice) {
 this.initPrice = lastPrice;
}
A: 
// while there are more lines
while(scanner.hasNextLine())
{
    final String   line;
    final String[] words;

    // get the next line
    line = scanner.nextLine();

    // break the line up into the words (\\s+ should break it up via whitespace)
    words = line.split("\\s");

    if(words.length != 5)
    {
        throw new WhateverExceptionMakesSense(line + " must contain 5 words");
    }

    System.out.println(currPriceMap.get(words[0]));
    System.out.println(pastPriceMap.get(words[1]));

    Move amove = new Move();
    amove.setSecCode(words[2]);
    amove.setPrice(currPriceMap.get(words[3]));
    amove.setInitPrice(pastPriceMap.get(words[4]));
    topMoves.add(amove);
}
TofuBeer
+3  A: 

Short answer:

For each call to hasNext() there should be only one call to next()

In your code you have 5 next() with only one hasNext()

Here, read this: http://java.sun.com/javase/6/docs/api/java/util/Iterator.html

EDIT

Longer answer:

Basically an iterator is used to ... well iterate the elements of "something" tipically a collection but it could be anything ( granted that anything returns an Iterator ).

Since you may not know how many elements does that "anything" have, there must be a way to stop iterating right? ( if it was an array, you can tell by the length property, but the iterator is used to "encapsulate" the data structure used in the implementation ) Anyway.

The iterator API defines these two methods

-hasNext(): boolean 
-next(): Object ( or <E> since Java 1.5 )

So the typical idiom is this:

 while( iterator.hasNext() ) { // reads: while the iterator has next element
      Object o = iterator.next(); //  give me that element
 }

What happens if the iterator has only two items?

 while( iterator.hasNext() ) { // the first time will return true, so the next line will be executed.

      Object o = iterator.next(); // give me that item. ( 1st element ) 

      Object b = iterator.next(); // oops dangerous by may work ... ( 2nd element ) 

      Object c = iterator.next(); // eeeerhhh... disaster: NoSuchElementException is thrown.

}

This is what is happening to you. You did not verify if the iterator has another element, you just retrieve it. If the iterator happens to have some elements, it may work for a while but there will be a time ( as you just saw ) when it fails.

By the way, DO NOT even think in catching NoSuchElementException. That's a runtime exception and it indicates that something in your code logic should be fixed.

See this answer to know more about the exceptions.

OscarRyz
Thanks.Replaced the iter.next() with secCodeIter and defined String secCodeIter = iter.next()
Ankur
+1  A: 

Here is a version using the new for loops:

for ( String secCode : secCodeList ) {

        System.out.println(currPriceMap.get(secCode));
        System.out.println(pastPriceMap.get(secCode));

        Move amove = new Move();
        amove.setSecCode(secCode);
        amove.setPrice(currPriceMap.get(secCode));
        amove.setInitPrice(pastPriceMap.get(secCode));
        topMoves.add(amove);
}

in the older fashion :

String secCode = null;    
for ( Iterator<String> it = secCodeList.iterator(); it.hasNext() ) {
    secCode = it.next();
    System.out.println(currPriceMap.get(secCode));
    System.out.println(pastPriceMap.get(secCode));

    Move amove = new Move();
    amove.setSecCode(secCode);
    amove.setPrice(currPriceMap.get(secCode));
    amove.setInitPrice(pastPriceMap.get(secCode));
    topMoves.add(amove);
 }
Clint
Its different as far as logic goes. currPrice and pastPrice is not the same even in the original post. :) No negative intended.
Adeel Ansari